【问题标题】:Programmatically deselect a row in a DataGrid以编程方式取消选择 DataGrid 中的一行
【发布时间】:2012-11-29 14:36:49
【问题描述】:

我正在努力寻找解决方案。

我想要做的是只在 DataGrid 中选择某些行。 SelectionMode 是 FullRow。一个例子是,如果用户试图拖动选择几行,而我不想选择其中之一。在这种情况下,我希望仍然选择有效行,而不是无效行。

有什么想法吗?

【问题讨论】:

  • 如何定义无效行?
  • 特定类型的项目将无效,因此类型检查将确定是否允许选择该行。

标签: c# wpf datagrid selection wpfdatagrid


【解决方案1】:

This guy wanted to do something alike with a ListBox。我相信该解决方案也可以适用于 DataGrid。

编辑

public static class DataGridRowEx
{
    public static bool GetCanSelect(DependencyObject obj)
    {
        return (bool)obj.GetValue(CanSelectProperty);
    }
    public static void SetCanSelect(DependencyObject obj, bool value)
    {
        obj.SetValue(CanSelectProperty, value);
    }
    public static readonly DependencyProperty CanSelectProperty =
        DependencyProperty.RegisterAttached("CanSelect", typeof(bool), typeof(DataGridRowEx), new UIPropertyMetadata(true, OnCanSelectChanged));

    private static void OnCanSelectChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var item = sender as DataGridRow;
        if (item == null)
            return;

        if ((bool)args.NewValue)
        {
            item.Selected -= RowSelected;
        }
        else
        {
            item.Selected += RowSelected;
            item.IsSelected = false;
        }
    }

    private static void RowSelected(object sender, RoutedEventArgs e)
    {
        var item = sender as DataGridRow;
        if (item == null)
            return;

        item.Dispatcher.BeginInvoke((Action)(()=>
        item.IsSelected = false));
    }
}

测试它:

public class ViewModel : INotifyPropertyChanged
{
    #region INotifyPropertyChanged values

    public event PropertyChangedEventHandler PropertyChanged;

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


    public List<Dummy> Elements { get; set; }

    public ViewModel()
    {
        this.Elements = new List<Dummy>(){
            new Dummy() { CanSelect =true, MyProperty = "Element1"},
            new Dummy() { CanSelect =false, MyProperty = "Element2"},
            new Dummy() { CanSelect =true, MyProperty = "Element3"},
            new Dummy() { CanSelect =false, MyProperty = "Element4"},
            new Dummy() { CanSelect =true, MyProperty = "Element5"},
            new Dummy() { CanSelect =true, MyProperty = "Element6"},
            new Dummy() { CanSelect =true, MyProperty = "Element7"},
            new Dummy() { CanSelect =true, MyProperty = "Element8"},
            new Dummy() { CanSelect =false, MyProperty = "Element9"},
        };
    }
}

public class Dummy
{
    public bool CanSelect { get; set; }

    public string MyProperty { get; set; }

    public override string ToString()
    {
        return this.MyProperty;
    }
}

<Window x:Class="WpfApplication1.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:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="525"
    Height="350"
    mc:Ignorable="d">
<Window.Resources>
    <Style x:Key="DataGridRowStyle" TargetType="{x:Type DataGridRow}">
        <Setter Property="local:DataGridRowEx.CanSelect" Value="{Binding CanSelect}" />
    </Style>
</Window.Resources>
<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>
<Grid x:Name="LayoutRoot">
    <DataGrid ItemsSource="{Binding Elements}"
              RowStyle="{DynamicResource DataGridRowStyle}"
              SelectionUnit="FullRow" />
</Grid>
</Window>

即使在按 shift 时,它也适用于多选。与 ListBoxItem 解决方案的唯一显着区别是取消选择必须使用 Dispatcher.BeginInvoke 进行排队,不知道为什么。 这种方法的唯一注意事项是,如果 DataGrid 具有单个选择项,则尝试选择一个不可选择的项会取消选择当前选定的项,如果 DataGrid 具有扩展选择项,则取消选择所有项。

【讨论】:

  • 嗯,我已经用我的代码尝试过,但无济于事。但是在测试项目中它可以工作,所以谢谢。我会尝试再次将它与我的代码集成。
  • 我需要为我的特定应用程序制定逻辑,但这有帮助。 item.Dispatcher.BeginInvoke((Action)(()=> item.IsSelected = false));线条是我需要的,谢谢。
【解决方案2】:

这不是最好的方法,但您可以创建一个继承类来保存网格的选定索引,然后如果选择了无效行,您只需将选定索引更改为最后一个有效索引

【讨论】:

  • 不幸的是,它需要能够进行多选。
  • 同样的事情,但有选定的行?
  • 这是一个dataGridView对象吧? yourgrid.SelectedRows 编辑:刚刚意识到 dataGrid 是一个单独的东西,对不起
【解决方案3】:

不是一个很好的解决方案,但您可以在 Mouse_Up 事件中取消选择行,所以让用户选择全部然后以编程方式取消选择,我没有测试过这个

private void dgvReport_MouseUp(object sender, MouseEventArgs e)
        {

            foreach (DataGridViewRow row in this.dgvReport.SelectedRows) {


                if (row.Cells[1].Value == "Invalid"){

                    this.dgvReport.Rows[row.Index].Selected = false;

                }


            }
        }

【讨论】:

  • 没有 Rows 属性。编辑:或 SelectedRows。
  • @JamieKelly 我假设您使用的是 DataGridView?
【解决方案4】:

这行得通,

        int row = grdexam.SelectedIndex;
        DataGridRow rv =(DataGridRow)this.grdexam.ItemContainerGenerator.ContainerFromIndex(row);
        DataRowView rvv =(DataRowView)rv.Item;
        MessageBox.Show(rvv.Row[1].ToString());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 2013-04-03
    相关资源
    最近更新 更多