WPF Custom control and display binding and specific data

FredGrit發表於2024-08-14
//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; }
    }
}

相關文章