绑定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 Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public 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>