[英]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员工对类似问题的评论似乎对我上述第二种解决方案是可以的。
我一直以为我在WPF表现不错,我一无所知。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.