我有两种不同的数据类型,用于在WPF数据网格上显示键和值。
public class Entry
{
public string Key { get; set; }
}
public class BoolRow : Entry
{
public bool Value { get; set; }
}
public class DoubleRow : Entry
{
public double Value { get; set; }
}
要修改BoolRow类型的值,我使用CheckBox,修改DoubleRow的值,我使用TextBox。这是通过TemplateSelectors实现的:
public class MyTemplateSelectorVal : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is BoolRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("ValueTemplateBool");
}
else if (item is DoubleRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("ValueTemplateDouble");
}
else
{
return null;
}
}
}
public class MyTemplateSelectorKey : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is BoolRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("KeyTemplate");
}
else if (item is DoubleRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("KeyTemplateEdit");
}
else
{
return null;
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<Entry> Rows = new ObservableCollection<Entry>();
public MainWindow()
{
Rows.Add(new DoubleRow() { Key = "DoubleRow1", Value = 1.1 }); //Key editable
Rows.Add(new DoubleRow() { Key = "DoubleRow2", Value = 3.1415 }); //Key editable
Rows.Add(new BoolRow() {Key = "BoolRow", Value=true}); //Key not editable
this.DataContext = Rows;
InitializeComponent();
}
}
MainWindow.xaml:
<Window x:Class="FocusTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FocusTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="KeyTemplate">
<TextBlock Text="{Binding Key}"/>
</DataTemplate>
<DataTemplate x:Key="KeyTemplateEdit">
<TextBox Text="{Binding Key}"/>
</DataTemplate>
<DataTemplate x:Key="ValueTemplateDouble">
<TextBox Text="{Binding Value}"/>
</DataTemplate>
<DataTemplate x:Key="ValueTemplateBool">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<local:MyTemplateSelectorKey x:Key="myTemplateSelectorKey"></local:MyTemplateSelectorKey>
<local:MyTemplateSelectorVal x:Key="myTemplateSelectorVal"></local:MyTemplateSelectorVal>
</Window.Resources>
<Grid>
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Key" CellTemplateSelector="{StaticResource myTemplateSelectorKey}" CellEditingTemplateSelector="{StaticResource myTemplateSelectorKey}"></DataGridTemplateColumn>
<DataGridTemplateColumn Header="Value" CellTemplateSelector="{StaticResource myTemplateSelectorVal}" CellEditingTemplateSelector="{StaticResource myTemplateSelectorVal}"></DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
窗口如下所示:
我想要实现的目标如下:
对于DoubleRows,键单元格的focusable属性应仅设置为true。 (双行的关键单元格应该是可聚焦和可编辑的,bool行的关键单元格不应该是可聚焦和可编辑的。)
当我在修改单元格后按Enter键时,焦点应移动到下一个可编辑单元格。 这意味着在修改值单元格后,焦点应向右移动,然后向下移动到下一个可编辑单元格。当下一行是DoubleRow类型时,关键单元格应该被聚焦,当下一行是BoolRow时,应该聚焦值单元格。
如果有人有解决方案会很好......?
答案 0 :(得分:0)
我找到了一个有效的解决方案:)
<强> XAML:强>
<Window x:Class="FocusTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FocusTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="KeyTemplate">
<TextBlock Text="{Binding Key}"/>
</DataTemplate>
<DataTemplate x:Key="KeyTemplateEdit">
<TextBox Text="{Binding Key}"/>
</DataTemplate>
<DataTemplate x:Key="ValueTemplateDouble">
<TextBox Text="{Binding Value}"/>
</DataTemplate>
<DataTemplate x:Key="ValueTemplateBool">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<local:MyTemplateSelectorKey x:Key="myTemplateSelectorKey"></local:MyTemplateSelectorKey>
<local:MyTemplateSelectorVal x:Key="myTemplateSelectorVal"></local:MyTemplateSelectorVal>
</Window.Resources>
<Grid>
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding}" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Key" CellTemplateSelector="{StaticResource myTemplateSelectorKey}" CellEditingTemplateSelector="{StaticResource myTemplateSelectorKey}">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=KeyFocusable}" Value="false">
<Setter Property="Focusable" Value="False"/>
</DataTrigger>
</Style.Triggers>
<EventSetter Event="KeyDown" Handler="myDataGridMain_KeyDown"></EventSetter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Value" CellTemplateSelector="{StaticResource myTemplateSelectorVal}" CellEditingTemplateSelector="{StaticResource myTemplateSelectorVal}">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<EventSetter Event="KeyDown" Handler="myDataGridMain_KeyDown"></EventSetter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
<强> CS:强>
public class Entry
{
public string Key { get; set; }
public bool KeyFocusable { get; set; }
}
public class BoolRow : Entry
{
public bool Value { get; set; }
public BoolRow()
{
KeyFocusable = false;
}
}
public class DoubleRow : Entry
{
public double Value { get; set; }
public DoubleRow()
{
KeyFocusable = true;
}
}
public class MyTemplateSelectorVal : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is BoolRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("ValueTemplateBool");
}
else if (item is DoubleRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("ValueTemplateDouble");
}
else
{
return null;
}
}
}
public class MyTemplateSelectorKey : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is BoolRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("KeyTemplate");
}
else if (item is DoubleRow)
{
return (DataTemplate)(container as FrameworkElement).FindResource("KeyTemplateEdit");
}
else
{
return null;
}
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<Entry> Rows = new ObservableCollection<Entry>();
public MainWindow()
{
Rows.Add(new DoubleRow() { Key = "DoubleRow1", Value = 1.1 }); //Key editable
Rows.Add(new DoubleRow() { Key = "DoubleRow2", Value = 3.1415 }); //Key editable
Rows.Add(new BoolRow() {Key = "BoolRow", Value=true}); //Key not editable
this.DataContext = Rows;
InitializeComponent();
}
private void myDataGridMain_KeyDown(object sender, KeyEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
if (e.Key == Key.Enter)
{
var uiElement = e.OriginalSource as UIElement;
if (e.Key == Key.Enter && uiElement != null)
{
e.Handled = true;
uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
}
}