2016-08-10 7 views
-1

У меня есть DataGrid, который использует виртуализацию, и один из столбцов использует DataGridTemplateColumn с ComboBox внутри. Однако, когда я прокручиваю влево/вправо в DataGrid (перемещая колонку ComboBox, а затем на просмотр), ComboBox теряет свой выбор.WPF DataGrid ComboBox Template Column потеряет выделение во время прокрутки

Настройка 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")); 
     } 
    } 
} 

ответ

0

Ключевой момент моего ответа заключается в том, что вам просто нужно связать свойство текста вашего комбо с UpdateSourceTrigger равен Изменено свойство.

Это единственное правильное решение. Не путайте другие нерелевантные детали. Если вы хорошо знаете WPF (и, к сожалению, очень мало людей здесь), вы должны знать, что 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); 
    } 
}