如何在属性与嵌套Style间创建Binding?XAML嵌套样式绑定问题
这个问题我之前也碰到过,核心原因是嵌套在Style里的内层Style没法直接继承外层控件的DataContext——毕竟Style作为资源,它的上下文和使用它的控件是分离的,所以你原来的绑定找不到对应的属性。下面给你几个可行的解决方案:
方案1:使用RelativeSource向上查找父控件
这是最稳妥的方法,通过指定父控件的类型,让Binding定位到外层控件的DataContext。你只需要把内层Style里的Binding改成下面这样,注意把AncestorType替换成实际使用这个Style的控件类型(比如DataGrid、Chart或者你的自定义控件):
<Setter Property="MajorGridLineStyle"> <Setter.Value> <Style TargetType="Line"> <Setter Property="Stroke" Value="{Binding DataContext.MajorGridLineStroke, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Mode=TwoWay}"/> <Setter Property="StrokeThickness" Value="{Binding DataContext.MajorGridLineStrokeThickness, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Mode=TwoWay}"/> </Style> </Setter.Value> </Setter>
如果你的控件层级比较深,还可以加上AncestorLevel来指定查找的层级,避免找到错误的父控件。
方案2:将内层Style放到ControlTemplate中
如果你的控件允许自定义模板,把内层的Line Style放到ControlTemplate里会更直接——因为ControlTemplate的上下文和控件本身是绑定的,里面的Binding可以直接访问控件的DataContext:
<Style TargetType="YourControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="YourControl"> <!-- 这里放控件的原有模板内容 --> <Line Stroke="{Binding MajorGridLineStroke, Mode=TwoWay}" StrokeThickness="{Binding MajorGridLineStrokeThickness, Mode=TwoWay}"/> <!-- 或者把Line的Style直接写在Template里 --> </ControlTemplate> </Setter.Value> </Setter> </Style>
这种方式不需要额外的上下文定位,代码更简洁,但前提是你能修改控件的模板。
方案3:使用{x:Reference}指定数据源(谨慎使用)
如果你的控件有固定的名称,也可以用{x:Reference}来直接绑定到控件的DataContext,但这种方法不适合资源被多个控件共享的场景,容易出现循环引用或者找不到控件的问题:
<Setter Property="MajorGridLineStyle"> <Setter.Value> <Style TargetType="Line"> <Setter Property="Stroke" Value="{Binding DataContext.MajorGridLineStroke, Source={x:Reference MyTargetControl}, Mode=TwoWay}"/> <Setter Property="StrokeThickness" Value="{Binding DataContext.MajorGridLineStrokeThickness, Source={x:Reference MyTargetControl}, Mode=TwoWay}"/> </Style> </Setter.Value> </Setter>
最后还要提醒一句:确保你的DataContext里的MajorGridLineStroke和MajorGridLineStrokeThickness属性要么是依赖属性,要么实现了INotifyPropertyChanged接口,否则双向绑定的更新不会生效哦。
内容的提问来源于stack exchange,提问作者Bart Van de Velde

