WPF DataGrid组合框模板列在滚动时丢失选择

时间:2016-08-10 22:13:38

标签: c# wpf wpfdatagrid

我有一个使用Virtualization的DataGrid,其中一列使用DataGridTemplateColumn和ComboBox。但是,当我在DataGrid中向左/向右滚动(将ComboBox列移出视图然后进入视图)时,ComboBox将丢失其选择。

设置EnableColumnVirtualization =“False”确实解决了问题,但后来我显然失去了列的虚拟化。

是否存在不涉及禁用虚拟化的解决方案?

我已经整理了一个简单的解决方案来证明这个问题。如果你运行它并且从左向右滚动非常快,你会看到ComboBox最终变空并且在它周围显示一个红色边框。

XAML:

<Window x:Class="SimpleReproTest.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" Loaded="Window_Loaded">
<Grid>
    <DataGrid x:Name="MyGrid" AutoGenerateColumns="False" EnableColumnVirtualization="True" EnableRowVirtualization="True" 
              VirtualizingStackPanel.VirtualizationMode="Standard" VirtualizingStackPanel.IsVirtualizing="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="ComboBox Column"/>
                    </DataTemplate>
                </DataGridTemplateColumn.HeaderTemplate>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding DummyItems}"
                                  SelectedValue="{Binding DummySelection}"
                                  SelectedValuePath="Key"
                                  DisplayMemberPath="Value"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
            <DataGridTextColumn Header="DummyColumn" Binding="{Binding Dummy}"></DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

代码背后:

using System.Collections.Generic;
using System.Windows;
using System.Collections.ObjectModel;

namespace SimpleReproTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<DummyColumn> MyData;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            MyData = new ObservableCollection<DummyColumn>();
            for (int i = 0; i < 50; i++)
                MyData.Add(new DummyColumn());

            MyGrid.ItemsSource = MyData;
        }
    }

    public class DummyColumn
    {
        public ObservableCollection<KeyValuePair<int, string>> DummyItems {get; set;}
        public string Dummy { get; set; }
        public int DummySelection { get; set; }

        public DummyColumn()
        {
            Dummy = "...";
            DummySelection = 0;
            DummyItems = new ObservableCollection<KeyValuePair<int,string>>();
            DummyItems.Add(new KeyValuePair<int,string>(0, "Item 0"));
            DummyItems.Add(new KeyValuePair<int,string>(1, "Item 1"));
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我的答案的关键是你只需要将组合的Text属性与UpdateSourceTrigger等于属性更改绑定。

这是唯一正确的解决方案。  不要被其他不相关的细节搞糊涂。如果你非常了解WPF(很遗憾,很少有人这么做)你必须要知道,当UI属性的更改源于UI对象本身时,OnPropertyChanged(或等效的通知程序)绝对无用。

尝试使用此xaml

<DataTemplate>
    <ComboBox ItemsSource="{Binding DummyItems}"
          SelectedValue="{Binding DummySelection}"
          SelectedValuePath="Key"
              Text="{Binding DummySel, UpdateSourceTrigger=PropertyChanged}"
          DisplayMemberPath="Value"/>
</DataTemplate>

和ViewModel

private string dummySel;
public string DummySel
{
    get { return dummySel; }
    set { dummySel = value;
        //OnPropertyChanged(() => DummySel);
    }
}
private int dummySelection;
public int DummySelection {
    get { return dummySelection;  }
    set {
        dummySelection = value;
        //OnPropertyChanged(()=>DummySelection); 
    }
}