【问题标题】:Set datagrid cells focusable property for specific data types and move focus to next editable cell为特定数据类型设置数据网格单元格可聚焦属性并将焦点移动到下一个可编辑单元格
【发布时间】:2015-05-22 20:49:21
【问题描述】:

我有 2 种不同的数据类型,用于在 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 的关键单元格的可聚焦属性才应设置为 true。 (双行的关键单元格应该是可聚焦和可编辑的,布尔行的关键单元格不应该是可聚焦和可编辑的。)

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

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

【问题讨论】:

  • 您需要网格的选择功能吗? (例如,选择一系列完整的行)。

标签: c# wpf datagrid


【解决方案1】:

我找到了一个可行的解决方案:)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多