我正在编写一个简单的wpf应用程序,其中包含datagrid。我正在遵循MVVM设计模式。最初运行应用程序时,将在数据网格中添加一个空行,默认情况下,我将焦点放在第一行的第一单元格上。
我需要完成以下工作,并且需要使用MVVM设计模式来完成它。
我发现了一些类似的问题(例如this),但是他们都没有解释如何使用MVVM设计模式来做到这一点,而我的第二点未包含在这些帖子中。
Item.cs类如下。
fail
ItemsViewModel.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;
}
}
在应用初始化时,跟随DataGridBehavior.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));
}
#region INotifyPropertyChanged Implementations
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Items.xaml用户控件如下。
public static class DataGridBehavior
{
public static readonly DependencyProperty FocusFirstCellProperty = DependencyProperty.RegisterAttached(
"FocusFirstCell", typeof(Boolean), typeof(DataGridBehavior), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnFocusFirstCellChanged)));
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 OnFocusFirstCellChanged(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;
}
}
MainWindow.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">
<TextBlock>Search</TextBlock>
<TextBox Text="{Binding Description}" />
<DataGrid x:Name="grdItems" ItemsSource="{Binding ItemsCollection}" AutoGenerateColumns="False" ColumnWidth="*"
local:DataGridBehavior.FocusFirstCell="True">
<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>
答案 0 :(得分:1)
此方法正常运行
dvSalesEntryDataGrid.PreviewKeyDown += Datagrid_PreviewKeyDown;
添加Datagrid PreviewKeyDown事件
if (e.Key == Key.Enter)
{
if (Keyboard.FocusedElement is UIElement elementWithFocus)
{
switch (dvDataGrid.CurrentCell.Column.DisplayIndex)
{
case 1:
DataGridRow currentrow5 = dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as DataGridRow;
elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
break;
case 2:
DataGridRow currentrow5 = dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as DataGridRow;
elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
break;
case n:
if (dvDataGrid.ItemsSource is ObservableCollection<DetailinfoModel> itemsSourcelast)
{
DataGridRow currentrow35 = dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as DataGridRow;
var newItem = new DetailinfoModel();
itemsSourcelast.Add(newItem);
dvDataGrid.SelectedItem = newItem;
Dispatcher.BeginInvoke(new Action(() =>
{
DataGridRow newRow = dvDataGrid.ItemContainerGenerator.ContainerFromItem(newItem) as DataGridRow;
DataGridCell cell = Helper.Helper.GetCell(dvSalesEntryDataGrid, newRow, 1);
if (cell != null)
dvDataGrid.CurrentCell = new DataGridCellInfo(cell);
}), DispatcherPriority.Background);
}
break; break;
default:
DataGridRow CurrentRowsdeault = dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as DataGridRow;
elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
break;
}
}
}