//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; }
}
}