繁体   English   中英

WPF ItemSource DataGrid TreeViewItem额外的行错误

[英]WPF ItemSource DataGrid TreeViewItem extra row bug

我看到一个奇怪的行为:我有一个TreeViewItem绑定到具有多行的源,如下所示:

<TreeViewItem Name="TreeViewItem1" >                                    
    <TreeViewItem.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding IP,FallbackValue=BindingError,Mode=TwoWay}" />
        </DataTemplate>
    </TreeViewItem.ItemTemplate>
</TreeViewItem>

在运行时绑定以下代码:

TreeViewItem1.ItemsSource = MySource;

到目前为止,它可以按预期工作:假设MySource中有2行-TreeViewItem显示2个子节点,并填充了正确的值。然后,我以类似的方式将DataGrid绑定到同一源:

<DataGrid Grid.Row="0" Name="MyDataGrid" AutoGenerateColumns="False" CanUserDeleteRows="True" >
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="IP" Binding="{Binding IP}" Header="IP" />
        <DataGridTextColumn x:Name="Port" Binding="{Binding Port}" Header="Port" />
    </DataGrid.Columns>
</DataGrid>

后面有代码

MyDataGrid.Items.Clear();
MyDataGrid.ItemsSource = MySource;

DataGird具有3行:MySource中有2行,其中填入了正确的值,另一行用于添加行。

问题:那就是,即使MySource仍然只有2,TreeViewItem也会获得3d子级。这没有任何意义,但这就是我所看到的。 好像DatGrid和TreeViewItem都未绑定到MySource,而是绑定到了模仿它的一些内部结构,该结构在2个控件之间共享。

可能无关紧要,但为了记录MySource,它是一个ObservableCollection,每个元素都实现INotifyPropertyChanged,因此在两个控件上都正确更新了添加/删除行以及更改每行的值。 唯一的问题是TreeViewItem中的多余行。

您是否尝试设置:

CanUserAddRows="False"

到您的数据网格? 我一直在设置它,然后使用按钮将行添加到数据网格中。 从我的角度来看,这对于我们的业务用户来说更有意义。

如果这对您不起作用,则也无法将datagrid和treeview绑定到相同的可观察集合,然后使树视图可观察集合保持同步。

另一个编辑仍然不是一个完美的解决方案,但是您的问题激起了我的兴趣。 我仍然喜欢用户单击按钮以添加项目;)。 这是我发现的。

如果我将TreeViewItem源设置为如下所示的集合视图:

窗口Xaml:

<Window x:Class="WpfApplication1.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" Background="Red" >
<Window.Resources>
            <CollectionViewSource x:Key="TreeViewCollection" Source="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="57*"/>
        <RowDefinition Height="125*"/>
        <RowDefinition Height="138*"/>
    </Grid.RowDefinitions>
    <TreeViewItem Name="TreeViewItem1" Background="White" Grid.RowSpan="3" IsExpanded="True" ItemsSource="{Binding Source ={StaticResource TreeViewCollection}}">
        <TreeViewItem.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ip,FallbackValue=BindingError,Mode=TwoWay}" />
            </DataTemplate>
        </TreeViewItem.ItemTemplate>
    </TreeViewItem>
    <DataGrid Grid.Row="2" Name="MyDataGrid" AutoGenerateColumns="False" CanUserDeleteRows="True" CanUserAddRows="True"
              ItemsSource="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="IP" Binding="{Binding ip}" Header="IP" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

背后的代码:

namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public ObservableCollection<Role> AllRoles { get; private set; }

    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>();
        allRoles.Add(new Role{ip = "bob"});
        allRoles.Add(new Role{ip = "john"});
        this.AllRoles = allRoles;

        TreeViewItemSource = GetNonsCollectionView(allRoles);
    }

    public CollectionView DataGridViewSource { get; private set; }
    public CollectionView TreeViewItemSource { get; private set; }

    public CollectionView GetNonsCollectionView(ObservableCollection<Role> nonsList)
    {
        return (CollectionView)CollectionViewSource.GetDefaultView(nonsList);
    }
}

public class Role : INotifyPropertyChanged
{
    public string ip { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

}

您将看到此工作。 我目前看到的问题是,当用户通过设置焦点将新行添加到网格时,正在更新集合视图。 我很累,否则我会进一步研究。

这是我一路上发现的一些链接。

MSFT员工对类似问题的评论似乎对我上述第二种解决方案是可以的。

MSFT论坛上的家伙描述了问题

我一直以为我在WPF表现不错,我一无所知。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM