将复杂的XAML绑定移动到样式设置器

时间:2018-01-05 01:42:41

标签: wpf xaml data-binding

我正在使用带有自定义样式和控件模板的复选框。我想将高度和宽度绑定移动到样式上,但我似乎无法做到正确。

这是XAML复选框

<CheckBox Style="{StaticResource MyCheckStyle}"
      HorizontalAlignment="Center"
      Height="{Binding FontSize, 
                       Source={x:Static gap:Settings.Default},
                       Converter={StaticResource MyMathConverter},
                       ConverterParameter='x+10'}"
      Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
      IsChecked="{Binding ValueT, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
      />
  • 我正在尝试创建一个复选框,其高度(以像素为单位)比当前字体大小大10分(一个黑客,但请暂时忽略它)。
  • 我将Width绑定到ActualHeight,以便它们始终是正方形(否则我的自定义模板将允许任何大小)
  • 我正在使用转换器(Ivan Krivyakov的MathConverter)进行数学计算。
  • 我绑定的大小存储在从设置文件生成的Settings类的静态实例中。

MyCheckStyle目前如下:

<Style x:Key="MyCheckStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template" Value="{StaticResource MyCheckBoxTemplate}" />
</Style>

到目前为止,这一切都很完美。但是我将 Width Binding移动到样式的尝试会使应用程序崩溃:

    <!-- WIDTH BINDING.  CAUSES A CRASH DUE TO ACCESS VIOLATION -->

    <Setter Property="Width">
        <Setter.Value>
            <Binding>
                <Binding.Source>
                    <RelativeSource Mode="Self"/>
                </Binding.Source>
                <Binding.Path>
                    <PropertyPath Path="ActualHeight"/>
                </Binding.Path>
            </Binding>
        </Setter.Value>
    </Setter>

我尝试移动高度绑定是完全失败的。我无法弄清楚如何在元素语法中复制“x:Static”标记扩展等等。 Intellisense / ReSharper对我帮助不大。

    <Setter Property="Height">
        <Setter.Value>
            <Binding>
            <!-- NO IDEA WHAT TO PUT HERE? -->
            </Binding>
        </Setter.Value>
    </Setter>

</Style>

任何人都能把我弄好吗?我正在做什么?

1 个答案:

答案 0 :(得分:2)

你有没有做过

Prop="{Binding Source={RelativeSouce ...}}"?

不。它不是Source,它是RelativeSource。大括号标记扩展语法设置与XML元素语法相同的属性,但使用花括号。就这样。如果它是带花括号的RelativeSource,它是带有尖括号的RelativeSource。

<Setter Property="Width">
    <Setter.Value>
        <Binding>
            <!-- RelativeSource, not Source -->
            <Binding.RelativeSource>
                <RelativeSource Mode="Self"/>
            </Binding.RelativeSource>
            <Binding.Path>
                <PropertyPath Path="ActualHeight"/>
            </Binding.Path>
        </Binding>
    </Setter.Value>
</Setter>

对于x:Static,这是另一个标记扩展(System.Windows.Markup.MarkupExtension的子类)。如果标记扩展类名称具有Extension后缀,则XAML解析器允许您省略“扩展”部分。因此它发生that class is actually named StaticExtension。如果您想在Foo.Bar命名空间中使用静态成员local,请轻松:

<x:StaticExtension Member="local:Foo.Bar" />

The Binding classMarkupExtension的子类(通过BindingBase),这就是为什么你可以使用大括号语法的原因。但是,它没有“扩展名”后缀。这是可选的。那里没有特别的一致性。

关键点:这些东西中的每一个都是一个类。 XAML是用于实例化类的实例并使用标量值或其他类实例初始化其属性的表示法。 Curly-brace标记扩展语法是一个有趣的小添加 - 但是一个有用的,因为你可以看到比较上面的XAML与我将建议作为替代。

现在,这一切都值得了解,但你不需要这里任何一个。

TL;博士

<Setter 
    Property="Width" 
    Value="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" 
    />
<Setter
    Property="Height"
    Value="{Binding FontSize, 
            Source={x:Static gap:Settings.Default},
            Converter={StaticResource MyMathConverter},
            ConverterParameter='x+10'}"
    />

完成。