代码之家  ›  专栏  ›  技术社区  ›  rasx

元素绑定到折叠的用户控件是一个草率、廉价的技巧吗?

  •  2
  • rasx  · 技术社区  · 15 年前

    我相信我们大多数人都会同意,陈述性的东西可能用完了。 DataContext 来源于 起源 自己 语境。然后我们可以求助于绑定到一个父节点 Tag 然后使用元素绑定。所以来源可能是这样的:

    <Grid.Tag>
        <Binding Path="MyProperty" Source="{StaticResource MySource}" />
    </Grid.Tag>
    

    当我们都做不到的时候会发生什么?我下一个草率的技巧是使用 UserControl 元素:

    <UserControl
        x:Name="MySloppyControl"
        DataContext="{StaticResource YetAnotherSourceInThisCrazyGrid}"
        Foreground={Binding CrazyForegroundColor}
        Visibility="Collapsed" />
    

    现在我可以做到:

    <Grid.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Foreground" Value="{Binding CrazyForegroundColor, ElementName=MySloppyControl}" />
        </Style>
    </Grid.Resources>
    

    假设我解释得很充分,这是不是崩溃了 用户控制 模式被误导了?

    1 回复  |  直到 15 年前
        1
  •  3
  •   Ray Burns    15 年前

    不是说我自己没有做过,而是我必须说“是的”——这种模式是错误的。

    在我选择这样做的少数情况下,我的代码如下所示:

    <Control x:Name="Whatever" DataContext="..." />
    <Control x:Name="SomethingElse" DataContext="..." />
    

    由于控件在默认情况下是不可见的,因此使用较少的代码可以获得相同的效果。

    话虽如此,让我解释一下为什么我认为这种做法是错误的:

    wpf就是绑定到数据。如果要绑定某些数据,则该数据可能是模型(或ViewModel)的一部分,也可能是外部数据。如果它是模型(或viewmodel)的一部分,并且模型的结构定义良好,那么您应该能够通过当前的datacontext访问它。另一方面,如果它是静态的,您应该能够直接从目标访问它。

    例如,假设您想用模型中所有可能的widgettype填充组合框。如果模型构造良好,则绑定可以简单到:

    <ComboBox ItemsSource="{Binding DataSet.AllWidgetTypes}" />
    

    这假设组合框的datacontext是一个“widget”,“widget”有一个“dataset”属性,允许访问其他相关数据。或者,如果可用类型的列表可能根据小部件的其他详细信息更改,则绑定可能只是 {Binding AppliableWidgetTypes} .

    另一种情况是,在引用静态对象(例如通过x:static或staticresource)时,您可能需要一个“单独的datacontext”。在这些情况下,有一个更好的方法:设置 Binding.Source . 看起来是这样的:

    Text="{Binding DefaultFontSize,Source={x:Static ApplicationProperties.Instance}}"
    

    或者这个

    Text="{Binding PropertyName,Source={StaticResource ResourceContainingProperty}}"
    

    如果您的动机是避免创建一个viewmodel来组合多个模型对象,那么使用c anonymoust类型来构造一个穷人的viewmodel。例如:

    DataContext = new { something = 123, whatever = "Test" };
    

    另一个常见模式是在控件上创建属性,并使用ControlTemplate和TemplateBinding绑定到它们。

    这就留下了最后一种情况,那就是你真的想要一个共享的值,而你根本不想留下任何代码。在这种情况下,我实际上已经开始使用隐形的 <Control> 如前所示。因此,在极少数情况下,它可能适用。

    推荐文章