私はこれに対する解決策を見つけるのに苦労しています。
私がやろうとしているのは、DataGridで特定の行のみを選択可能にすることです。SelectionModeはFullRowです。例として、ユーザーがいくつかの行をドラッグ選択しようとした場合、そのうちの1つを選択可能にしたくない場合があります。この場合、有効な行を引き続き選択しますが、無効な行は選択しません。
何か案は?
私はこれに対する解決策を見つけるのに苦労しています。
私がやろうとしているのは、DataGridで特定の行のみを選択可能にすることです。SelectionModeはFullRowです。例として、ユーザーがいくつかの行をドラッグ選択しようとした場合、そのうちの1つを選択可能にしたくない場合があります。この場合、有効な行を引き続き選択しますが、無効な行は選択しません。
何か案は?
これを行うための最良の方法ではありませんが、グリッドの選択されたインデックスを保持する継承されたクラスを作成し、無効な行が選択された場合は、選択されたインデックスを最後の有効なインデックスに変更するだけです。
この男は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に拡張選択がある場合はすべての選択が解除されることです。
優れたソリューションではありませんが、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;
}
}
}
これはうまくいくでしょう、
int row = grdexam.SelectedIndex;
DataGridRow rv =(DataGridRow)this.grdexam.ItemContainerGenerator.ContainerFromIndex(row);
DataRowView rvv =(DataRowView)rv.Item;
MessageBox.Show(rvv.Row[1].ToString());