绑定到 DataGrid 的 SelectedItems 不通知目标
Bound-to DataGrid's SelectedItems not Notifying Target
我正在将 Button
的 IsEnabled
属性 绑定到 DataGrid
的 SelectedItems
的数量。
XAML :
<DataGrid SelectionChanged="DG_Reports_OnSelectionChanged" x:Name="DG_Reports" SelectionMode="Extended" ItemsSource="{Binding Reportslists, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=Explicit}" AutoGenerateColumns="False" CanUserAddRows="True" CanUserReorderColumns="False" CanUserDeleteRows="True">
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Grid>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGridRow}}}"/>
</Grid>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
<DataGrid.Columns>
<!-- Columns Here -->
</DataGrid.Columns>
</DataGrid>
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" IsEnabled="{Binding ElementName=DG_Reports, NotifyOnSourceUpdated=True, Path=SelectedItems, Converter={StaticResource SelectedDataGridRowsToBooleanConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<command:EventToCommand Command="{Binding DeleteReports}" CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
SelectedDataGridRowsToBooleanConverter 转换器:
public class SelectedDataGridRowsToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((IList<Object>) value).Count > 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
一开始(意味着当 DataGrid 中没有选择任何东西时)按钮成功未启用,但是一旦我开始选择行,没有任何反应,我应该注意到 DataGrid 的 SelectionChanged
事件正常触发,但是按钮永远不会收到选择更改的通知,我可能在这里遗漏了什么?
对于DataGrid,SelectedItems是一个集合,不能像上面那样使用。相反,您可以使用 SelectedItems.Count 并如下所述更改转换器。
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" IsEnabled="{Binding ElementName=DG_Reports,
NotifyOnSourceUpdated=True, Path=SelectedItems.Count, Converter={StaticResource SelectedDataGridRowsToBooleanConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<command:EventToCommand Command="{Binding DeleteReports}" CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
public class SelectedDataGridRowsToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value > 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
实现此功能的其他方式。在这你需要写转换器。命令的 CanExecute 方法,用于启用和禁用按钮。您不需要对按钮使用交互触发器,因为它已经将命令 属性 关联到单击事件。参考下面的代码。
<StackPanel>
<DataGrid x:Name="DG_Reports" Height="200"
AutoGenerateColumns="False"
ItemsSource="{Binding SampleItems}" >
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Grid>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay,
RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGridRow}}}"/>
</Grid>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding DayOfMonth}">
</DataGridTextColumn>
<DataGridTextColumn Header="Day" Binding="{Binding Weekday}">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" Command="{Binding DeleteReports}"
CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}">
</Button>
</StackPanel>
public class Item
{
public int DayOfMonth { get; set; }
public string Weekday { get; set; }
}
public class MainViewModel
{
private ObservableCollection<Item> m_items;
public ObservableCollection<Item> SampleItems
{
get { return m_items; }
set { m_items=value; }
}
public ICommand DeleteReports { get; private set; }
public MainViewModel()
{
DeleteReports = new RelayCommand<object>(Delete,CanDelete);
var items = new ObservableCollection<Item>();
var today = DateTime.Now;
for (int i = 1; i <= DateTime.DaysInMonth(today.Year, today.Month); i++)
{
items.Add(new Item { DayOfMonth = i, Weekday = new DateTime(today.Year, today.Month, i).DayOfWeek.ToString() });
}
SampleItems = items;
}
private void Delete(object obj)
{
var items = new ObservableCollection<Item>();
foreach (var item in (IList)obj)
{
items.Add((Item)item);
}
foreach (var item in items)
{
m_items.Remove(item);
}
}
private bool CanDelete(object obj)
{
return ((IList)obj).Count > 0;
}
}
我正在将 Button
的 IsEnabled
属性 绑定到 DataGrid
的 SelectedItems
的数量。
XAML :
<DataGrid SelectionChanged="DG_Reports_OnSelectionChanged" x:Name="DG_Reports" SelectionMode="Extended" ItemsSource="{Binding Reportslists, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=Explicit}" AutoGenerateColumns="False" CanUserAddRows="True" CanUserReorderColumns="False" CanUserDeleteRows="True">
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Grid>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGridRow}}}"/>
</Grid>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
<DataGrid.Columns>
<!-- Columns Here -->
</DataGrid.Columns>
</DataGrid>
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" IsEnabled="{Binding ElementName=DG_Reports, NotifyOnSourceUpdated=True, Path=SelectedItems, Converter={StaticResource SelectedDataGridRowsToBooleanConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<command:EventToCommand Command="{Binding DeleteReports}" CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
SelectedDataGridRowsToBooleanConverter 转换器:
public class SelectedDataGridRowsToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((IList<Object>) value).Count > 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
一开始(意味着当 DataGrid 中没有选择任何东西时)按钮成功未启用,但是一旦我开始选择行,没有任何反应,我应该注意到 DataGrid 的 SelectionChanged
事件正常触发,但是按钮永远不会收到选择更改的通知,我可能在这里遗漏了什么?
对于DataGrid,SelectedItems是一个集合,不能像上面那样使用。相反,您可以使用 SelectedItems.Count 并如下所述更改转换器。
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" IsEnabled="{Binding ElementName=DG_Reports,
NotifyOnSourceUpdated=True, Path=SelectedItems.Count, Converter={StaticResource SelectedDataGridRowsToBooleanConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<command:EventToCommand Command="{Binding DeleteReports}" CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
public class SelectedDataGridRowsToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value > 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
实现此功能的其他方式。在这你需要写转换器。命令的 CanExecute 方法,用于启用和禁用按钮。您不需要对按钮使用交互触发器,因为它已经将命令 属性 关联到单击事件。参考下面的代码。
<StackPanel>
<DataGrid x:Name="DG_Reports" Height="200"
AutoGenerateColumns="False"
ItemsSource="{Binding SampleItems}" >
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Grid>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay,
RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGridRow}}}"/>
</Grid>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding DayOfMonth}">
</DataGridTextColumn>
<DataGridTextColumn Header="Day" Binding="{Binding Weekday}">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="Bt_RemoveReports" Content="Supprimer Rapport" Command="{Binding DeleteReports}"
CommandParameter="{Binding ElementName=DG_Reports, Path=SelectedItems}">
</Button>
</StackPanel>
public class Item
{
public int DayOfMonth { get; set; }
public string Weekday { get; set; }
}
public class MainViewModel
{
private ObservableCollection<Item> m_items;
public ObservableCollection<Item> SampleItems
{
get { return m_items; }
set { m_items=value; }
}
public ICommand DeleteReports { get; private set; }
public MainViewModel()
{
DeleteReports = new RelayCommand<object>(Delete,CanDelete);
var items = new ObservableCollection<Item>();
var today = DateTime.Now;
for (int i = 1; i <= DateTime.DaysInMonth(today.Year, today.Month); i++)
{
items.Add(new Item { DayOfMonth = i, Weekday = new DateTime(today.Year, today.Month, i).DayOfWeek.ToString() });
}
SampleItems = items;
}
private void Delete(object obj)
{
var items = new ObservableCollection<Item>();
foreach (var item in (IList)obj)
{
items.Add((Item)item);
}
foreach (var item in items)
{
m_items.Remove(item);
}
}
private bool CanDelete(object obj)
{
return ((IList)obj).Count > 0;
}
}