单击嵌套项时,WPF Datagrid不会失去焦点

时间:2017-03-31 14:02:53

标签: wpf datagrid nested focus edit

我有一个带有模板列的数据网格,它嵌套了另一个数据网格。当我在主数据网格上编辑一个人的名字,然后双击编辑嵌套项目时,主要的一个不会失去焦点,以便单元格保持编辑模式。

Here is the picture

我通过为嵌套数据网格注册GotFocus事件来处理它,使用自定义FindAncestor函数在可视树中查找父数据网格并在主数据网格上调用CancelEdit()。

private void DataGridItem_GotFocus(object sender, RoutedEventArgs e)
        {
            var dg =(DataGrid)FindAncestor((DependencyObject)sender, typeof(DataGrid), 2);
            dg.CancelEdit();
        }

这实在是太过分了。是否有一种不同的MVVM方式可以解决这个问题?

以下是此简化示例的完整代码。

XAML

<Grid>
        <DataGrid x:Name="DataGrid1"
                  ItemsSource="{Binding DataCollection}"
                  SelectedItem="{Binding DataCollectionSelectedItem}"
                  AutoGenerateColumns="False" 
                  CanUserAddRows="false" >
            <DataGrid.Resources>
                <Style TargetType="DataGridCell">
                    <Setter Property="Background" Value="LightBlue"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="2*" />
                <DataGridTemplateColumn Header="Item/Price" Width="3*">
                    <DataGridTemplateColumn.CellTemplate >
                        <DataTemplate>
                            <DataGrid x:Name="DataGridItem" 
                                      ItemsSource="{Binding Items}"
                                      SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ItemsSelectedItem}"
                                      GotFocus="DataGridItem_GotFocus"
                                      Background="Transparent"
                                      HeadersVisibility="None"
                                      AutoGenerateColumns="False"
                                      CanUserAddRows="false" >
                                <DataGrid.Columns>
                                    <DataGridTextColumn Binding="{Binding ItemName}" Width="*"/>
                                    <DataGridTextColumn Binding="{Binding Price}" Width="50"/>
                                </DataGrid.Columns>
                            </DataGrid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

C#

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace datagrid_focus
{
    public class Item : NotifyObject
    {
        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set { _itemName = value; OnPropertyChanged("ItemName"); }
        }
        private double _price;
        public double Price
        {
            get { return _price; }
            set { _price = value; OnPropertyChanged("Price"); }
        }
    }

    public class Person : NotifyObject
    {
        public ObservableCollection<Item> Items { get; set; }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> DataCollection { get; set; }
        public Person DataCollectionSelectedItem { get; set; }
        public Item ItemsSelectedItem { get; set; }

        public ViewModel()
        {
            DataCollection = new ObservableCollection<Person>
            {
                new Person {Name = "Siegmund Freud", Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Phone", Price = 220 },
                        new Item { ItemName = "Tablet", Price = 350 },
                    } },
                new Person {Name = "Karl Popper", Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Teddy Bear Deluxe", Price = 2200 },
                        new Item { ItemName = "Pokemon", Price = 100 }
                    }}
            };
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }

        public DependencyObject FindAncestor(DependencyObject current, Type type, int levels)
        {
            int currentLevel = 0;
            while (current != null)
            {
                if (current.GetType() == type)
                {
                    currentLevel++;
                    if (currentLevel == levels)
                    {
                        return current;
                    }
                }
                current = VisualTreeHelper.GetParent(current);
            };
            return null;
        }

        private void DataGridItem_GotFocus(object sender, RoutedEventArgs e)
        {
            var dg =(DataGrid)FindAncestor((DependencyObject)sender, typeof(DataGrid), 2);
            //dg.CancelEdit();
        }
    }
}

0 个答案:

没有答案