【问题标题】:WPF DataGrid ComboBox Template Column Loses the Selection While ScrollingWPF DataGrid 组合框模板列在滚动时丢失选择
【发布时间】:2016-08-10 22:13:38
【问题描述】:

我有一个使用虚拟化的 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"));
        }
    }
}

【问题讨论】:

    标签: c# wpf wpfdatagrid


    【解决方案1】:

    我回答的重点是,您只需要将组合的 Text 属性与 UpdateSourceTrigger 绑定为 Property Changed 即可。

    这是唯一正确的解决方案。 不要被其他不相关的细节所迷惑。如果您非常了解 WPF(不幸的是,这里很少有人这样做),您必须意识到当 UI 属性的更改源于 UI 对象本身时,OnPropertyChanged(或等效通知程序)绝对没用。

    试试这个 xaml

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

    和视图模型

    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); 
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 2013-09-30
      • 2018-06-24
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      相关资源
      最近更新 更多