【问题标题】:How to programmatically bind a (dependency) property of a control that's inside a DataTemplate?如何以编程方式绑定 DataTemplate 中控件的(依赖项)属性?
【发布时间】:2014-03-12 08:45:59
【问题描述】:

TextBlock 位于DataTemplate 中,因此我无法通过它的名称来引用它。那么如何以编程方式绑定其(例如)Text 属性?

XAML:

<UserControl x:Class="MyNameSpace.MyCustomControl" ... >
    ...
    <ListBox ItemsSource="{Binding Path=ItemsSource}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    ...
</UserControl>

代码:

public partial class MyCustomControl : UserControl {
    ...

    public static readonly DependencyProperty DataSourceProperty =
        DependencyProperty.Register("DataSource", typeof (IEnumerable),
                                    typeof (MyCustomControl),
                                    new PropertyMetadata(default(IEnumerable)));

    public IEnumerable DataSource {
        get { return (IEnumerable) GetValue(DataSourceProperty); }
        set { SetValue(DataSourceProperty, value); }
    }

    public static readonly DependencyProperty MemberPathProperty =
        DependencyProperty.Register("MemberPath", typeof (string),
                                    typeof (MyCustomControl),
                                    new PropertyMetadata(default(string)));

    public string MemberPath {
        get { return (string) GetValue(MemberPathProperty); }
        set { SetValue(MemberPathProperty, value); }
    }
    ...
    public MyCustomControl() {
        InitializeComponent();

        var binding = new Binding(MemberPath);
        BindingOperations.SetBinding(/*how do I refer to the TextBlock here ???*/,
                                     TextBox.TextProperty, binding);
    }
    ...
}

预期使用示例:

<my:MyCustomControl DataSource="{Binding Path=SomeModelCollection}" MemberPath="Name"

其中SomeModelCollection 是一些数据模型属性,例如ObservableCollection&lt;SomeModel&gt;SomeModel 有一个名为Name 的属性)

【问题讨论】:

  • d 'Textblock' 打算展示什么......作为 'MemberPath' 是什么...... d itemsource 是什么......
  • @Sankarann - 我添加了MemberPath - 它旨在从外部绑定TextBlockPath 属性(即在我嵌入MyCustomControl 的XAML 中)
  • @Sankarann - 还添加了一个预期的用法示例
  • 所以MemberPath 只有一个值,并且与TextBox.Text.. 绑定意味着所有列表项将显示与MemberPath.. 中相同的值。对吗?
  • 这里每个ListItem 都持有MyModel 作为它的DataContext。因此,如果您想绑定Name,您可以使用&lt;TextBlock Text="{Binding Name}"/&gt;... 仍然不清楚您与MemberPathTextBlock.Text 的关系如何......

标签: c# wpf binding datatemplate


【解决方案1】:

您可以使用VisualTreeHelper 获取TextBlock。此方法将为您获取 listBoxItem 的 Visual 树中存在的所有 TextBlock:

public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj)
            where T : DependencyObject
{
   if( depObj != null )
   {
       for( int i = 0; i < VisualTreeHelper.GetChildrenCount( depObj ); i++ )
       {
          DependencyObject child = VisualTreeHelper.GetChild( depObj, i );
          if( child != null && child is T )
          {
              yield return (T)child;
          }

          foreach( T childOfChild in FindVisualChildren<T>( child ) )
          {
             yield return childOfChild;
          }
       }
    }
}

用法:

TextBlock textBlock = FindVisualChildren<TextBlock>(listBoxItem)
                       .FirstOrDefault();

但我仍然建议在 XAML 中进行绑定,而不是在后面的代码中进行。

如果ItemSourceObservableCollection&lt;MyModel&gt; 并且MyModel 包含属性Name,则可以像这样在XAML 中完成:

<DataTemplate>
   <StackPanel Orientation="Horizontal">
      <TextBlock Text="{Binding Name}"/>
   </StackPanel>
 </DataTemplate>

由于DataContextListBoxItem 将是MyModel,因此您可以像上面提到的那样直接绑定到 Name 属性。

【讨论】:

  • 如何在 XAML 中做到这一点?
  • 更新了我的答案。看看吧。
  • 但我将它绑定到ObservableCollection&lt;MyModel&gt;,其中MyModel 有一个名为stringstring 字段Name。这不是一个简单的ObservableCollection&lt;string&gt;
  • 而且提供的代码不起作用——首先,它必须在构造函数完成后调用,其次它必须在每次列表更改时调用,所以它不是真正的绑定。 ..
  • 你需要简单的"{Binding Name}"。检查答案中的更新。
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 2013-01-01
  • 1970-01-01
  • 2012-08-07
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2012-09-06
相关资源
最近更新 更多