WPF简单的User Control

很早以前就接触了WPF,可是一直没怎么仔细研究过。最近做Windows Phone时又开始接触相关内容。在一个功能中,需要显示一些保存的城市列表,决定用自定义控件做。因为以前没仔细学习WPF,现在就趁着用到看了点。

=================以下段落转自网络并做出了修改====================

我们为控件(或者任何一个WPF 类)添加的依赖属性都是"公开的","静态的","只读的",其命名方式是"属性名+Property",这是依赖属性一成不变的
书写方式.对于依赖属性的注册可以在声明该属性时就调用DependencyProperty.Register()方法注册,也可以在其静态构造方法中注册.上面的
DependencyProperty.Register 方法的几个参数分别是:属性名(该属性名与声明的依赖属性名称"XXXProperty"相比仅仅是少了"Property"
后缀,其它完全一样,否则在运行时会报异常),属性的数据类型,属性的拥有者的类型,元数据.
关于参数中传递的元数据: 如果是普通的类则应该传递PropertyMetadata, 如果是FrameworkElement 则可以传递
FrameworkPropertyMetadata, 其中FrameworkPropertyMetadata 中可以制定一些标记表明该属性发生变化时控件应该做出什么反应,比如某
属性的变化会影响到该控件的绘制, 那么就应该像这样书写该属性的元数据: new FrameworkPropertyMetadata(defauleValue,
FrameworkPropertyMetadataOptions.AffectsRender);这样当该属性发生变化时系统会考虑重绘该控件.另外元数据中还保护很多内容,比
如默认值,数据验证,数据变化时的回调函数,是否参与属性"继承"等.
然后,我们将该依赖属性包装成普通属性:
 1 [Description("获取或设置当前城市")]
 2 [Category("Common Properties")]
 3 public string City
 4 {
 5 get
 6 {
 7 return (string)this.GetValue(CityProperty);
 8 } set
 9 {
10 this.SetValue(CityProperty, value);
11 }
12 }


GetValue 和SetValue 方法来自于DependencyObject 类,其用于获取或设置类的某属性值.
注意:在将依赖属性包装成普通属性时,在get 和set 块中除了按部就班的调用GetValue 和SetValue 方法外,不要进行任何其它的操作.下面的代码
是不恰当的:

 1         [Description("获取或设置当前气温")]
 2         [Category("Common Properties")]
 3         public string Temperature
 4         {
 5             get
 6             {
 7                 return (string)this.GetValue(TemperatureProperty);
 8             }
 9             set
10             {
11                 this.SetValue(TemperatureProperty, value);
12                 this.OnTimeUpdated(value);//Error
13             }
14         }


在以前这或许是很多人的惯用写法,但在WPF 中,这样的写法存在潜在的错误,原因如下:我们知道继承于DependencyObject 的类拥有GetValue 和
SetValue 方法来获取或设置属性值,那为什么我们不直接使用该方法来获取或设置属性值,而要将其包装成普通的.NET 属性呢,事实上在这里两种方
式都是可以的,只不过包装成普通的.NET 属性更符合.NET 开发人员的习惯,使用GetValue 和SetValue 更像JAVA 开发人员的习惯,但XAML 在执
行时似乎于JAVA 开发人员一样,其不会调用.NET 属性而是直接使用GetValue 或SetValue 方法,这样一来,我们写在get 块和set 块中的其它代
码根本不会被XAML 执行到.所以说,就上面的Time 属性而言,C#(或其它)对该属性的调用不会出现任何问题,但该属性被用在XAML 中时(比如在XAML
对该属性进行数据绑定等),其set 块中的this.OnTimeUpdated(value);语句不会被执行到.
那么,当Time 属性发生变化时的确需要调用this.OnTimeUpdated(value); 语句(因为该语句会引发时间被更新了的事件),还是在传递的依赖属性
元数据做文章:
new FrameworkPropertyMetadata(DateTime.Now,new PropertyChangedCallback(TimePropertyChangedCallback)), 我们为属性
的变化指定了一个回调函数,当该属性变化时该回调函数就会被执行

==================页面设计======================

View Code
 1     <Grid Name="gd" Height="200" Width="200">
 2         <Grid.RowDefinitions>
 3             <RowDefinition Height="*"/>
 4             <RowDefinition Height="*"/>
 5         </Grid.RowDefinitions>
 6         <Grid.ColumnDefinitions>
 7             <ColumnDefinition Width="*"/>
 8             <ColumnDefinition Width="*"/>
 9         </Grid.ColumnDefinitions>
10 
11         <TextBlock Name="txtCity" Grid.Row="0" Grid.Column="0" FontSize="40" FontFamily="Microsoft YaHei">
12             <TextBlock.BitmapEffect >
13                 <OuterGlowBitmapEffect Opacity="0.6"></OuterGlowBitmapEffect>
14             </TextBlock.BitmapEffect>
15         </TextBlock>
16         <TextBlock Name="txtTemp" Grid.Row="1" Grid.Column="0" FontSize="40" FontFamily="Microsoft YaHei">
17             <TextBlock.BitmapEffect >
18                 <OuterGlowBitmapEffect Opacity="0.6"></OuterGlowBitmapEffect>
19             </TextBlock.BitmapEffect>
20         </TextBlock>
21         <Image Grid.Row="0" Grid.Column="1" Name="img" ></Image>
22     </Grid>

==================后台代码======================

View Code
namespace userC
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class UserControl1 : UserControl
    {

        #region DP
        public string City
        {
            get
            {
                return (string)this.GetValue(CityProperty);
            }
            set
            {
                SetValue(CityProperty, value);
            }
        }



        public static DependencyProperty CityProperty = DependencyProperty.Register("City", typeof(string), typeof(UserControl1), new PropertyMetadata("长春"));

        public string Temperature
        {
            get
            {
                return (string)this.GetValue(TemperatureProperty);
            }
            set
            {
                SetValue(TemperatureProperty, value);
            }
        }

        public static DependencyProperty TemperatureProperty = DependencyProperty.Register("Temperature", typeof(string), typeof(UserControl1), new PropertyMetadata("20"));

        public string ImagePath
        {
            get
            {
                return (string)this.GetValue(ImagePathProperty);
            }
            set
            {
                SetValue(ImagePathProperty, value);
            }
        }

        public static DependencyProperty ImagePathProperty = DependencyProperty.Register("ImagePath", typeof(string), typeof(UserControl1), new PropertyMetadata("null"));

        public Brush Background
        {
            get
            {
                return (Brush)this.GetValue(BackgroundProperty);
            }
            set
            {
                SetValue(BackgroundProperty, value);
            }
        }

        public static DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Brush), typeof(UserControl1), new PropertyMetadata(Brushes.Cyan));

        #endregion


        public UserControl1()
        {
            InitializeComponent();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            Binding cityBinding = new Binding();
            cityBinding.Source = this;
            cityBinding.Path = new PropertyPath(UserControl1.CityProperty);
            this.txtCity.SetBinding(TextBlock.TextProperty, cityBinding);

            Binding temBinding = new Binding();
            temBinding.Source = this;
            temBinding.Path = new PropertyPath(UserControl1.TemperatureProperty);
            this.txtTemp.SetBinding(TextBlock.TextProperty, temBinding);

            Binding imgBinding = new Binding();
            imgBinding.Source = this;
            imgBinding.Path = new PropertyPath(UserControl1.ImagePathProperty);
            this.img.SetBinding(Image.SourceProperty, imgBinding);

            Binding bgBinding = new Binding();
            bgBinding.Source = this;
            bgBinding.Path = new PropertyPath(UserControl1.BackgroundProperty);
            this.gd.SetBinding(Grid.BackgroundProperty, bgBinding);
        }
    }
}

==================前台调用======================

先引用User Control工程

using userC;

然后在WrapPanel里面添加自定义控件

1   public MainWindow()
2         {
3             InitializeComponent();
4 
5             wp.Children.Add(new UserControl1 { City = "宿迁", Temperature = "25", ImagePath = "/usercontrol;component/晴D.png", Background = Brushes.Pink });
6             wp.Children.Add(new UserControl1 { City = "长春", Temperature = "10", ImagePath = "/usercontrol;component/多云D.png", Background = Brushes.RosyBrown });
7             wp.Children.Add(new UserControl1 { City = "北京", Temperature = "15", ImagePath = "/usercontrol;component/冻雨N.png" });
8         }

工程源码

原文地址:https://www.cnblogs.com/NailClipper/p/2691527.html