//Custom Control //xaml <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp242"> <Style TargetType="{x:Type local:BookBox}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:BookBox}"> <Border Background="Cyan" BorderBrush="Cyan" BorderThickness="3" Width="150" Height="90"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <TextBlock Text="Id:" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding IdInt,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="Name:" Grid.Row="1" Grid.Column="0"/> <TextBlock Text="{Binding NameStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1"/> <TextBlock Text="Title:" Grid.Row="2" Grid.Column="0"/> <TextBlock Text="{Binding TitleStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> //cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp242 { /// <summary> /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file. /// /// Step 1a) Using this custom control in a XAML file that exists in the current project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp242" /// /// /// Step 1b) Using this custom control in a XAML file that exists in a different project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp242;assembly=WpfApp242" /// /// You will also need to add a project reference from the project where the XAML file lives /// to this project and Rebuild to avoid compilation errors: /// /// Right click on the target project in the Solution Explorer and /// "Add Reference"->"Projects"->[Browse to and select this project] /// /// /// Step 2) /// Go ahead and use your control in the XAML file. /// /// <MyNamespace:BookBox/> /// /// </summary> public class BookBox : Control { static BookBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(BookBox), new FrameworkPropertyMetadata(typeof(BookBox))); } public BookBox() { this.DataContext = this; } public int IdInt { get { return (int)GetValue(IdIntProperty); } set { SetValue(IdIntProperty, value); } } // Using a DependencyProperty as the backing store for IdInt. This enables animation, styling, binding, etc... public static readonly DependencyProperty IdIntProperty = DependencyProperty.Register("IdInt", typeof(int), typeof(BookBox), new PropertyMetadata(0)); public string NameStr { get { return (string )GetValue(NameStrProperty); } set { SetValue(NameStrProperty, value); } } // Using a DependencyProperty as the backing store for NameStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty NameStrProperty = DependencyProperty.Register("NameStr", typeof(string ), typeof(BookBox), new PropertyMetadata("")); public string TitleStr { get { return (string )GetValue(TitleStrProperty); } set { SetValue(TitleStrProperty, value); } } // Using a DependencyProperty as the backing store for TitleStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitleStrProperty = DependencyProperty.Register("TitleStr", typeof(string ), typeof(BookBox), new PropertyMetadata("")); } }
//whole code //custom control.xaml <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp242"> <Style TargetType="{x:Type local:BookBox}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:BookBox}"> <Border Background="Cyan" BorderBrush="Cyan" BorderThickness="3" Width="150" Height="90"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <TextBlock Text="Id:" Grid.Row="0" Grid.Column="0"/> <TextBlock Text="{Binding IdInt,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="Name:" Grid.Row="1" Grid.Column="0"/> <TextBlock Text="{Binding NameStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1"/> <TextBlock Text="Title:" Grid.Row="2" Grid.Column="0"/> <TextBlock Text="{Binding TitleStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> //custom control.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp242 { /// <summary> /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file. /// /// Step 1a) Using this custom control in a XAML file that exists in the current project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp242" /// /// /// Step 1b) Using this custom control in a XAML file that exists in a different project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp242;assembly=WpfApp242" /// /// You will also need to add a project reference from the project where the XAML file lives /// to this project and Rebuild to avoid compilation errors: /// /// Right click on the target project in the Solution Explorer and /// "Add Reference"->"Projects"->[Browse to and select this project] /// /// /// Step 2) /// Go ahead and use your control in the XAML file. /// /// <MyNamespace:BookBox/> /// /// </summary> public class BookBox : Control { static BookBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(BookBox), new FrameworkPropertyMetadata(typeof(BookBox))); } public BookBox() { this.DataContext = this; } public int IdInt { get { return (int)GetValue(IdIntProperty); } set { SetValue(IdIntProperty, value); } } // Using a DependencyProperty as the backing store for IdInt. This enables animation, styling, binding, etc... public static readonly DependencyProperty IdIntProperty = DependencyProperty.Register("IdInt", typeof(int), typeof(BookBox), new PropertyMetadata(0)); public string NameStr { get { return (string )GetValue(NameStrProperty); } set { SetValue(NameStrProperty, value); } } // Using a DependencyProperty as the backing store for NameStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty NameStrProperty = DependencyProperty.Register("NameStr", typeof(string ), typeof(BookBox), new PropertyMetadata("")); public string TitleStr { get { return (string )GetValue(TitleStrProperty); } set { SetValue(TitleStrProperty, value); } } // Using a DependencyProperty as the backing store for TitleStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitleStrProperty = DependencyProperty.Register("TitleStr", typeof(string ), typeof(BookBox), new PropertyMetadata("")); } } //mainwindow.xaml.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp242 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private List<Book> booksList { get; set; } Random rnd { get; set; } private int width { get; set; } private int height { get; set; } public MainWindow() { InitializeComponent(); this.Loaded += MainWindow_Loaded; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { width = (int)(this.ActualWidth-100); height=(int)(this.ActualHeight-100); rnd = new Random(); booksList = new List<Book>(); for(int i=0;i<10;i++) { booksList.Add(new Book() { Id=i+1, Name=$"Name_{i+1}", Title=$"Title_{i+1}" }); } DrawBookBoxInCanvas(); } private void DrawBookBoxInCanvas() { if(booksList==null || !booksList.Any()) { return; } int len = booksList.Count; Canvas cvs = new Canvas(); for(int i=0;i<len;i++) { BookBox bb = new BookBox(); bb.IdInt = booksList[i].Id; bb.NameStr= booksList[i].Name; bb.TitleStr= booksList[i].Title; Canvas.SetLeft(bb, rnd.Next(0,width)); Canvas.SetTop(bb, rnd.Next(0,height)); if(!cvs.Children.Contains(bb)) { cvs.Children.Add(bb); } } this.Content = cvs; } } public class Book { public int Id { get; set; } public string Name { get; set; } public string Title { get; set; } } }