为特定数据类型设置datagrid单元格可聚焦属性,并将焦点移动到下一个可编辑单元格

时间:2015-03-19 16:11:36

标签: c# wpf datagrid

我有两种不同的数据类型,用于在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>

窗口如下所示:

Window

我想要实现的目标如下:

对于DoubleRows,键单元格的focusable属性应仅设置为true。 (双行的关键单元格应该是可聚焦和可编辑的,bool行的关键单元格不应该是可聚焦和可编辑的。)

当我在修改单元格后按Enter键时,焦点应移动到下一个可编辑单元格。 这意味着在修改值单元格后,焦点应向右移动,然后向下移动到下一个可编辑单元格。当下一行是DoubleRow类型时,关键单元格应该被聚焦,当下一行是BoolRow时,应该聚焦值单元格。

如果有人有解决方案会很好......?

1 个答案:

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