WPF中Binding
绑定ViewModel中的数据
添加数据上下文
方法一:在XAML中添加
<Window.DataContext><local:MainWindowViewModel />
</Window.DataContext>
方法二:在界面层的cs文件中添加
this.DataContext = new MainWindowViewModel();
绑定
public string Message { get; set; } = "Hello World";
<TextBlock Text="{Binding Path=Message}" Margin="10"/>
//简写此一个参数默认是Path
<TextBlock Text="{Binding Message}" Margin="10"/>
//什么都不屑默认绑定DataContext
<TextBlock Text="{Binding}" Margin="10"/>
绑定资源字典
简单的绑定资源字典的数据
<Window.DataContext><local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources><sys:String x:Key="str">Hello, World</sys:String>
</Window.Resources>
<Grid><TextBlock Text="{Binding Source={StaticResource str}}" Margin="10"/>//简写<TextBlock Text="{staticResource str}" Margin="10"/>//绑定动态资源只能这样简写,写完整会报错<TextBlock Text="{DynamicResource str}" Margin="10"/>
</Grid>
绑定cs文件中资源字典的数据
先定义一个类
class MyResourece
{public string Message { get; } = "Public Property";public static string StaticString = "Static String";public const string ConstString = "Const String";
}
把类读取到资源字典
<Window.Resources><local:MyResourece x:Key="mysource" />
</Window.Resources>
对于静态,常量,enum,都得用x:Staic来访问,普通的资源可以用StaticResource
<TextBlock Text="{Binding Source={StaticResource mysource},Path=Message}"/>
//静态和常量得用x:Static访问
<TextBlock Grid.Row="1" Text="{Binding Source={x:Static local:MyResourece.ConstString}}" />
<TextBlock Grid.Row="2" Text="{Binding Source={x:Static local:MyResourece.StaticString}}" />
绑定控件
ElementName
<StackPanel><TextBox x:Name="txt" /><TextBlock Text="{Binding ElementName=txt, Path=Text}" />
</StackPanel>
x:Reference
当ElementName失效时可以用x:Reference,这是通用什么情况下都可以用
TextBlock Text="{Binding Source={x:Reference Name=txt},Path=Text}" />
RelativeSource
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window},Path=Top}" />
我想读取到tag1的写法,当有多个相同的属性可以用AncestorLevel=3,标识找到父级第三个Grid
<Grid Tag="tag1"><Grid Tag="tag2"><Grid Tag="tag3"><TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Grid,AncestorLevel=3},Path=Tag}" /></Grid></Grid>
</Grid>
用ReletiveSource绑定同级别控件
<StackPanel><TextBox /><TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=StackPanel},Path=Children[0].Text}" />
</StackPanel>
绑定自己的写法四种写法
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualWidth}" />
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=ActualWidth}" />
<TextBlock Text="{Binding RelativeSource={x:Static RelativeSource.Self},Path=ActualWidth}" />
<TextBlock Text="{Binding RelativeSource={RelativeSource 2},Path=ActualWidth}" />
绑定模板的属性,两种先给发等价
<StackPanel><Label Padding="10"><Label.Template><ControlTemplate TargetType="Label"><Border Padding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Padding}"><ContentPresenter /></Border></ControlTemplate></Label.Template></Label>
</StackPanel>
<StackPanel><Label Padding="10"><Label.Template><ControlTemplate TargetType="Label"><Border><ContentPresenter Margin="{TemplateBinding Padding}" /></Border></ControlTemplate></Label.Template></Label>
</StackPanel>
StringFormat
StringFormat可以指定格式,:F3表示小数点后三位小数
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=Top,StringFormat='Top:{0:F3}'}" />
MultiBinding
<StackPanel><TextBlock><TextBlock.Text><MultiBinding StringFormat="Pos:{0},{1}"><Binding Path="Top"RelativeSource="{RelativeSource AncestorType=Window}" /><Binding Path="Left"RelativeSource="{RelativeSource AncestorType=Window}" /></MultiBinding></TextBlock.Text></TextBlock>
</StackPanel>
有Content属性的控件,可以用ContentStringFormat
<StackPanel><Label Content="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=Top}"ContentStringFormat="Top:{0:F3}" />
</StackPanel>
FallbackValue和TargetNullValue
FallbackValue在没有绑定成功时优先显示
TargetNullValue在绑定的值为空时优先显示
<Label Content="{Binding Message,FallbackValue=dasdaa,TargetNullValue=asdasd}"/>
对比
RelativeSource、ElementName、x:Reference中前两者依赖对象树寻找关系,x:Reference可以从文档搜索,前两者绑定失效可以用x:Reference
x:Reference的缺陷,无法绑定自己的父级
BindingProxy
public class BindingProxy : Freezable
{#region Overrides of Freezableprotected override Freezable CreateInstanceCore(){return new BindingProxy();}#endregionpublic object Data{get { return (object)GetValue(DataProperty); }set { SetValue(DataProperty, value); }}// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...public static readonly DependencyProperty DataProperty =DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
<Window.Resources><local:MyResourece x:Key="mysource" /><local:BindingProxy x:Key="mybtn"Data="{Binding ElementName=btn}" />
</Window.Resources>
<StackPanel><Button Name="btn"Content="Click Me"><Button.ToolTip><ToolTip><StackPanel><TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Content}" /><TextBlock Text="{Binding Source={StaticResource mybtn},Path=Data.Content}" /></StackPanel></ToolTip></Button.ToolTip></Button>
</StackPanel>