在XAML中绑定位于Itemscontrol之外的属性

13

我试图绑定一个在ItemsControl之外的属性。但是这似乎不起作用。

在ItemsControl的DataTemplate中,它似乎只引用集合内部的内容而不是集合外部的内容。我已经试过使用RelativeResource和AncestorType引用ViewModel。

代码(VM):

public class Test {
  public string GetThis {get{return "123";} set{}}
  public List<string> IterateProperty {get; set;}
}

XAML(视图):

<ItemsControl ItemsSource="{Binding Path=IterateProperty}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="I want to bind the string property GetThis!" />

你能否检查一下我定义属性的示例?它可能会有所帮助。 - Olaru Mircea
2个回答

16

你需要将当前元素的DataContext绑定到父级ItemsControlDataContext上。

<ItemsControl ItemsSource="{Binding Path=IterateProperty}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding DataContext.GetThis,
                                RelativeSource={RelativeSource Mode=FindAncestor,
                                                               AncestorType={x:Type ItemsControl}}}" />

好的,很精准,但我仍然遇到了一个错误。但现在它说:无法解析类型为“System.Windows.Controls.ItemsControl”的数据上下文中的属性“...” 噢不 :( - Khiem-Kim Ho Xuan
看起来我仍然遇到了同样的问题。我正在使用Caliburns MVVM。(抱歉,忘记提到这一点了) - Khiem-Kim Ho Xuan
如果GetThisIterateProperty都在同一个公共类中...那么Mike的代码肯定可以工作。@Khiem-KimHoXuan,你确定没有忘记一些重要的代码吗? - almulo
看起来现在它可以工作了。我不得不仔细检查我的代码。使用UserControl的Datacontext.Propertyname解决了我的问题。 - Khiem-Kim Ho Xuan
@almulo请注意,AncestorType=ItemsControl也是有效的XAML。您的编辑对此帖子没有太大贡献。 - Clemens
3
哦,好的,那部分修改并不重要……我只是为了在代码中添加上下文而进行编辑。这可能只是一个小的补充,但对于某些困惑于RelativeSource绑定的人来说,这样可以更清晰地看到它。 - almulo

5
我已经为此制作了一个快速而完整的示例:

我已经为此制作了一个快速而完整的示例:

<Window x:Class="ParentDataContext.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid ItemsSource="{Binding items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox IsChecked="{Binding IsChecked}"></CheckBox>
                            <TextBlock Margin="5" 
                                       Text="{Binding Path=DataContext.TextFromParent,RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

每行的上下文都设置为绑定列表中的每个对象。在我们的情况下,是来自items集合的每个Model实例。

要返回到父级的DataContext,使用以下语法:

Text="{Binding Path=DataContext.TextFromParent,RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>

以下是代码后端的内容:
public partial class MainWindow : Window
{
    public string TextFromParent
    {
        get { return (string)GetValue(TextFromParentProperty); }
        set { SetValue(TextFromParentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for TextFromParent.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextFromParentProperty =
        DependencyProperty.Register("TextFromParent", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));


    public ObservableCollection<Model> items { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        items = new ObservableCollection<Model>();
        items.Add(new Model() { IsChecked = true });
        items.Add(new Model() { IsChecked = false });
        items.Add(new Model() { IsChecked = true });
        items.Add(new Model() { IsChecked = false });
        TextFromParent = "test";
        this.DataContext = this;
    }
}

您可以在ViewModel中定义您的依赖属性。

这是我的简单Model:

public class Model : INotifyPropertyChanged
{
    private bool _IsChecked;

    public bool IsChecked
    {
        get { return _IsChecked; }
        set
        {
            _IsChecked = value;
            PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

因此,您可以访问在父级DataContext中定义的属性。 enter image description here

谢谢兄弟,这很有帮助。 - Khiem-Kim Ho Xuan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接