【问题标题】:Focus wpf datagrid cell using mvvm design pattern使用 mvvm 设计模式聚焦 wpf 数据网格单元
【发布时间】:2019-12-12 23:30:46
【问题描述】:

我正在使用 MVVM 设计模式编写简单的 WPF 应用程序。我的应用程序包含一个带有单个数据网格视图的用户控件。数据网格的每个单元格都是一个文本框列。

我想要的是在数据网格视图中设置焦点第一个单元格的文本框。

我尝试了this 解决方案,它适用于文本框。但它不适用于网格单元内的文本框。

Item.cs 类如下。

public class Item
{
    public string ItemCode { get; set; }
    public string ItemName { get; set; }
    public double ItemPrice { get; set; }

    public Item(string itemCode,string itemName, double itemPrice)
    {
        this.ItemCode = itemCode;
        this.ItemName = itemName;
        this.ItemPrice = itemPrice;
    }
}

ItemsViewModel.cs 类如下

public class ItemsViewModel : INotifyPropertyChanged
{
    private List<Item> _items;

    public List<Item> ItemsCollection
    {
        get { return this._items; }
        set
        {
            _items = value;
            OnPropertyChanged(nameof(ItemsCollection));
        }
    }

    public ItemsViewModel()
    {
        this.ItemsCollection = new List<Item>();
        this.ItemsCollection.Add(new Item("", "", 0));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Item.xaml 用户控件如下。

<UserControl x:Class="WpfApp2.Items"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:WpfApp2"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <StackPanel Orientation="Vertical">
        <DataGrid x:Name="grdItems" ItemsSource="{Binding ItemsCollection}" AutoGenerateColumns="False" ColumnWidth="*">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Item Code">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="txtItemCode" Text="{Binding ItemCode}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Item Name">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="txtItemName" Text="{Binding ItemName}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Price">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="txtItemSellingPrice" Text="{Binding ItemPrice}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Grid>

MainWindow.xaml 如下。

<Window x:Class="WpfApp2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <local:Items/>
</Grid>

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    一旦加载了DataGrid,您可以实现一个附加行为,在可视化树中找到TextBox

    public static class DataGridBehavior
    {
        public static readonly DependencyProperty FocusFirstCellProperty = DependencyProperty.RegisterAttached(
            "FocusFirstCell", typeof(Boolean), typeof(DataGridBehavior), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnChanged)));
    
        public static void SetFocusFirstCell(DataGrid element, Boolean value)
        {
            element.SetValue(FocusFirstCellProperty, value);
        }
    
        public static Boolean GetFocusFirstCell(DataGrid element)
        {
            return (Boolean)element.GetValue(FocusFirstCellProperty);
        }
    
        private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGrid element = (DataGrid)d;
            if (element.IsLoaded)
            {
                TextBox textBox = FindVisualChild<TextBox>(element);
                if (textBox != null)
                    Keyboard.Focus(textBox);
            }
            else
            {
                RoutedEventHandler handler = null;
                handler = (ss, ee) =>
                {
                    DataGrid dataGrid = (DataGrid)ss;
                    TextBox textBox = FindVisualChild<TextBox>((DataGrid)ss);
                    if (textBox != null)
                        Keyboard.Focus(textBox);
                    dataGrid.Loaded -= handler;
                };
                element.Loaded += handler;
            }
        }
    
        private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is T)
                    return (T)child;
                else
                {
                    T childOfChild = FindVisualChild<T>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }
    }
    

    用法:

    <DataGrid x:Name="grdItems" ItemsSource="{Binding ItemsCollection}"... 
        local:DataGridBehavior.FocusFirstCell="True">
    

    【讨论】:

      【解决方案2】:

      了解FocusManager 的工作原理。 :)

      如果您需要一些不太正式的描述,请查看 here

      例子:

      <TextBox FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-24
        • 1970-01-01
        • 2019-12-13
        • 1970-01-01
        • 2014-06-17
        • 2013-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多