WPF简单的User Control

来源:互联网 发布:数据恢复软件代理 编辑:程序博客网 时间:2024/06/05 19:04

原文地址:http://www.cnblogs.com/NailClipper/archive/2012/09/18/2691527.html

很早以前就接触了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             set10             {11                 this.SetValue(TemperatureProperty, value);12                 this.OnTimeUpdated(value);//Error13             }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         }
复制代码

 

 

工程源码


原创粉丝点击