【问题标题】:Get Ancestor Source in Wpf在 Wpf 中获取祖先源
【发布时间】:2017-03-21 18:17:37
【问题描述】:

我正在尝试将祖先 ItemsControl.ItemTemplate 源作为我的 DataGrid 源,但我无法处理这种情况。我在我的 xaml 中尝试了以下案例。但它不起作用,datagrid 是空的。

这是我的 xaml:

<ItemsControl ItemsSource="{Binding Accounts}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Expander ExpandDirection="Down" FlowDirection=" RightToLeft">
                <Expander.Header>
                    <DataGrid FlowDirection="LeftToRight"
                            ItemsSource="{RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemTemplate}}}">
                        <DataGrid.Columns>
                            <DataGridTextColumn Binding="{Binding UserName}" />
                            <DataGridTextColumn Binding="{Binding Password}" />
                        </DataGrid.Columns>
                    </DataGrid>
                </Expander.Header>
           </Expander>
      </DataTemplate>
   </ItemsControl.ItemTemplate>

Accounts 属性实现如下:

public List<User> Accounts = new List<User>();
Accounts.Add(new User("userName1","password1"));
Accounts.Add(new User("userName2","password2"));

而我的 User.cs 是这样的:

public class User : INotifyPropertyChanged
{
        public string UserName{get; set;}
        public string Password{get; set;}


       public UserAccount(string userName, string password)
       {
          UserName = userName;
          Password = password;
       }
 }

【问题讨论】:

    标签: c# wpf xaml binding datacontext


    【解决方案1】:

    基本上,这段代码不会创建绑定

    ItemsSource="{RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemTemplate}}}"
    

    祖先类型也不正确。

    试试这个绑定:

    ItemsSource="{Binding Path=DataContext.Accounts, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"
    

    或使用元素名称:

    <ItemsControl Name="LstAccounts" ItemsSource="{Binding Accounts}">
    

    ItemsSource="{Binding Path=DataContext.Accounts, ElementName=LstAccounts}"
    

    上面的代码修复了绑定,但产生了意想不到的结果。这是在 DataGrid 中显示单个对象的解决方案

    对于 ItemSource 绑定,我创建了一个转换器 (my own older answer)

    public class ItemsSourceConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // doesn't allow to add new rows in DataGrid
            return Enumerable.Repeat(value, 1).ToArray();            
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    这里是修改过的ItemsControl。转换器存储在资源中并在 ItemsSource 绑定中使用。 DataGrid 自动生成列

    <ItemsControl ItemsSource="{Binding Accounts}">
        <ItemsControl.Resources>
            <local:ItemsSourceConverter x:Key="Enumerator"/>
        </ItemsControl.Resources>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Expander ExpandDirection="Down" FlowDirection=" RightToLeft">
                    <Expander.Header>
                        <DataGrid FlowDirection="LeftToRight" 
                                  ItemsSource="{Binding ., Converter={StaticResource Enumerator}}"/>
                    </Expander.Header>
                </Expander>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    这是截图

    【讨论】:

    • 此绑定有效,但问题是它绑定了帐户中的所有项目。问题是,我只想将每个项目绑定到不同的 expanderHeader。我的意思是,这个绑定就像 DataGridSource = Accounts 但我想要像 DataGridSource = Account
    • @stackerflow,我重新阅读了这个问题,并感到困惑为什么 ItemTemplate 包含 ExpanderDataGrid(在标题中),而 items 是一个只有 2 个属性的简单用户对象。也许使用 DataGrid 而不是 ItemsControl?像这样:&lt;DataGrid ItemsSource="{Binding Path=Accounts"&gt; &lt;DataGrid.Columns&gt; &lt;DataGridTextColumn Binding="{Binding UserName}" &gt; &lt;DataGridTextColumn Binding="{Binding Password}" /&gt; &lt;/DataGrid.Columns&gt; &lt;/DataGrid&gt;
    • 好吧,我在扩展器内容下有一些可编辑的文本框和项目相关菜单,我在发布问题时将其删除,以免人们因超载信息而感到困惑。需要明确的是:我只想获取项目上下文而不是扩展器内的列表上下文。顺便说一句,感谢您的帮助。
    • 好的,如果 Header 应该显示单个用户的信息,我不会使用 DataGrid(这让我很困惑,尽管即使是单个项目也可能)。我会使用带有一些控件的面板,例如:&lt;Expander.Header&gt; &lt;StackPanel Orientation="Horizontal"&gt; &lt;TextBlock Text="{Binding UserName}" /&gt; &lt;TextBlock Text="{Binding Password}" /&gt; &lt;/StackPanel&gt; &lt;/Expander.Header&gt;。这当然是原始的,需要像字幕一样改进,但显示了这个想法
    • 关键是 StackPanel 非常原始,设计它对我来说看起来非常复杂。我只是喜欢数据网格的可视化,这就是我选择它的原因。如果您有任何关于将 stackpanel 可视化转换为 dataGridRow 样式的解决方案,那么它也会非常有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多