控件上当某些数据需要根据其他数据的变化而变化 很多时候,想让某个控件的宽度或者高度是另一个已有控件的一半,一开始打算使用ObjectDataProvider
来实现,因为在控件上当某些数据需要根据其他数据的变化而变化时,可以使用ObjectDataProvider
,这个类提供了一种将XAML绑定方法的行为。
案例:实现两个文本框,第一个文本框的数据是第二个文本框的一半
写一个方法 1 2 3 4 5 6 7 public class MethodClass { public string Calculator (string p ) { return (int .Parse(p) * 0.5 ).ToString(); } }
在Resources中声明一个ObjectDataProvider
1 2 3 4 5 6 7 8 9 10 <Window.Resources > <ObjectDataProvider x:Key ="dataObj" MethodName ="Calculator" ObjectType ="{x:Type local:MethodClass}" > <ObjectDataProvider.MethodParameters > <sys:String > 200</sys:String > </ObjectDataProvider.MethodParameters > </ObjectDataProvider > </Window.Resources >
使用ObjectDataProvider
1 2 3 4 5 6 <StackPanel > <TextBlock Text ="{Binding Source={StaticResource dataObj}}" /> <TextBox Text ="{Binding Source={StaticResource dataObj}, Path=MethodParameters[0], UpdateSourceTrigger=PropertyChanged, BindsDirectlyToSource=True}" /> </StackPanel >
但是很难在resources的ObjectDataProvider.MethodParameters
集合中绑定某个控件的宽度,所以放弃使用这种办法。
实现某个控件宽度为另一控件的一半 很多时候,想让某个控件的宽度或者高度是另一个已有控件的一半,即Width={Binding Path=Width,ElementName=otherContol}/2
,但是XAML中不支持直接运算,这样写是错误 的。实现这种效果当然可以后台写C#代码实现,但是这么简单的功能我只想用XAML来实现,我的方法是借助UniformGrid
来实现。
示例 :让button按钮的宽度为窗体宽度的1/4
1 2 3 4 5 6 7 8 9 <StackPanel > <UniformGrid Columns ="4" > <Border x:Name ="bor" /> </UniformGrid > <Button Width ="{Binding ElementName=bor, Path=ActualWidth}" Content ="OK" /> </StackPanel >
可以看到button的宽度时刻保持为窗体宽度的1/4
静态属性的绑定 非静态属性的绑定非常容易
1 2 3 4 5 public class MethodClass { public int MyProperty { get ; set ; } public static int MyStaticProperty { set ; get ; } }
可以在Resources中增加一个资源,在XAML中增加local:MethodClass节点意味着创建一个local:MethodClass实例,非静态属性可以直接在后面写出。
1 2 3 <Window.Resources > <local:MethodClass x:Key ="k1" MyProperty ="11" /> </Window.Resources >
但是静态属性是不能写出的
而且,静态属性的访问方式是 静态类名称.静态属性
,所以在XAML中进行静态绑定可以这样:
1 2 3 4 <TextBlock Text ="{Binding Path=(local:MethodClass.MyStaticProperty)}" /> <TextBlock Text ="{Binding Path=MyStaticProperty, Source={StaticResource k1}}" />
静态属性的变化通知 非静态属性的变化通知可以继承INotifyPropertyChanged
来实现,在非静态属性的set方法中调用事件的Invoke。但是静态属性PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyStaticProperty"));
这样写是错误的,因为访问不到this。
静态属性的通知有两种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class MethodClass { public int MyProperty { get ; set ; } private static int _value = 50 ; public static int MyStaticProperty { get { return _value; } set { _value = value ; MyStaticPropertyChanged.Invoke(null , new PropertyChangedEventArgs("MyStaticProperty" )); StaticPropertyChanged.Invoke(null , new PropertyChangedEventArgs("MyStaticProperty" )); } } public static event EventHandler<PropertyChangedEventArgs> MyStaticPropertyChanged; public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged; }
建议使用第二种方法,原因是1.名称固定,不易出错。2.当类中有多个静态属性时,使用第一种方法要声明多个EventHandler,而第二种方法只需要一个就可以。
为了验证结果,写一个修改静态属性的方法
1 2 3 4 5 6 7 8 9 10 11 12 Task.Run(() => { int i = 0 ; while (true ) { Task.Delay(500 ).Wait(); this .Dispatcher.Invoke(() => { MethodClass.MyStaticProperty = i++; }); } });
可以看到绑定了静态属性的textblox在不停的变化