我正在为使用datagrid的学生记录创建一个C#wpf应用程序。 如何在标题中创建复选框以选择/取消选中连续的所有复选框? 如何通过点击选择行中的复选框,以便我们可以编辑/删除记录?以及我们如何选择多个复选框来删除?Datagrid中的复选框wpf c#应用程序
2
A
回答
0
使用某事像这样:
DataGridCheckBoxColumn cbc = new DataGridCheckBoxColumn();
dataGrid.Columns.Add(cbc);
CheckBox cb = new CheckBox();
cbc.Header = cb;
和处理Checked
和UnChecked
事件:
cb.Checked+=new RoutedEventHandler(cb_Checked);
cb.Unchecked+=new RoutedEventHandler(cb_Unchecked);
2
我创建了一个行为,允许在控制属性绑定到的属性以下列方式收集项目:
- 如果更改控件中的属性,则所有项目更新。
- 如果您更改项目中的属性,如果所有项目具有相同的属性,控件将反映它。如果不是,控件的属性将被赋予一个回退值(如null)。
有了这种行为,您可以将复选框添加到您的DataGrid标题并将其IsChecked属性绑定到DataGrid的ItemSource,以集合类型的属性。
我们可以使用MVVM模式处理选择逻辑。例如,我们有以下视图模型的收藏单位:
public class ItemViewModel : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private bool isSelected;
public bool IsSelected {
get { return this.isSelected; }
set
{
if (this.isSelected == value)
return;
this.isSelected = value;
this.OnPropertyChanged("IsSelected");
}
}
private string myProperty;
public string MyProperty
{
get { return this.myProperty; }
set
{
if (this.myProperty != value)
{
this.myProperty = value;
this.OnPropertyChanged("MyProperty");
}
}
}
}
然后我们有MainViewModel,控制主窗口的逻辑:
public class MainViewModel: INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region Items (INotifyPropertyChanged Property)
private ObservableCollection<ItemViewModel> items;
public ObservableCollection<ItemViewModel> Items
{
get { return this.items; }
set
{
if (this.items != value)
{
this.items = value;
this.OnPropertyChanged("Items");
}
}
}
#endregion
public MainViewModel()
{
this.Items = new ObservableCollection<ItemViewModel>();
for (int i = 0; i < 10; i++)
this.Items.Add(new ItemViewModel() { MyProperty = "Item" + i });
}
}
在我们的窗口,我们可以宣布DataGrid中。为了达到你想要什么,我们将不得不为以下内容:
- 分配MainViewModel到Window.DataContext
- 绑定DataGrid.ItemsSource在MainViewModel
- 项目属性定义的列DataGrid。在这个例子中,我选择了一个“IsSelected”列,并按照您的指定将“SelectAll”复选框添加到其标题中,但是您可以在任何地方使用CheckBox来控制选择。
- 我们需要使行的选择更新我们项目的“IsSelected”属性,反之亦然。为此,我们修改RowStyle,以便我们可以将行的“IsSelected”属性绑定到其项目的“IsSelected”。因此,现在选择逻辑可以完全由ViewModel驱动。
- 最后要做的就是让“SelectAll”复选框执行其工作。我们应用CollectionPropertyBehavior并对其进行配置,使其“SourcePropertyPath”指向我们想要绑定的CheckBox中的属性(“IsChecked”),CollectionPropertyPath指向项中的属性(“IsSelected”)。然后我们只需要将它的ItemsSource绑定到DataGridItemsSource。请注意,默认值为“null”,这意味着当项目的属性中具有不同的值时,CheckBox将收回“null”并处于未定义状态。
最终的XAML将是这样的:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication2" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="WpfApplication2.MainWindow"
Title="MainWindow" mc:Ignorable="d" Height="350" Width="525">
<Window.Resources>
<Style x:Key="DataGridRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</Style>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items}" CanUserAddRows="False" RowStyle="{DynamicResource DataGridRowStyle}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsSelected}">
<DataGridCheckBoxColumn.Header>
<CheckBox>
<i:Interaction.Behaviors>
<local:CollectionPropertyBehavior CollectionPropertyPath="IsSelected" SourcePropertyPath="IsChecked" ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</i:Interaction.Behaviors>
</CheckBox>
</DataGridCheckBoxColumn.Header>
</DataGridCheckBoxColumn>
<DataGridTextColumn Width="*" Binding="{Binding MyProperty}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
最后,行为:
public class CollectionPropertyBehavior : Behavior<DependencyObject>
{
private IEnumerable<ValueProxy> proxies;
private bool syncking;
public string SourcePropertyPath
{
get { return (string)GetValue(SourcePropertyPathProperty); }
set { SetValue(SourcePropertyPathProperty, value); }
}
public static readonly DependencyProperty SourcePropertyPathProperty =
DependencyProperty.Register("SourcePropertyPath", typeof(string), typeof(CollectionPropertyBehavior), new PropertyMetadata(null));
public string CollectionPropertyPath
{
get { return (string)GetValue(CollectionPropertyPathProperty); }
set { SetValue(CollectionPropertyPathProperty, value); }
}
public static readonly DependencyProperty CollectionPropertyPathProperty =
DependencyProperty.Register("CollectionPropertyPath", typeof(string), typeof(CollectionPropertyBehavior), new PropertyMetadata(null));
private IEnumerable<object> Items { get { return this.ItemsSource == null ? null : this.ItemsSource.OfType<object>(); } }
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CollectionPropertyBehavior), new PropertyMetadata(null, ItemsSourceChanged));
private object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(CollectionPropertyBehavior), new PropertyMetadata(null, ValueChanged));
public object DefaultValue
{
get { return (object)GetValue(DefaultValueProperty); }
set { SetValue(DefaultValueProperty, value); }
}
public static readonly DependencyProperty DefaultValueProperty =
DependencyProperty.Register("DefaultValue", typeof(object), typeof(CollectionPropertyBehavior), new PropertyMetadata(null));
private static void ValueChanged(object sender, DependencyPropertyChangedEventArgs args)
{
var element = sender as CollectionPropertyBehavior;
if (element == null || element.ItemsSource == null) return;
element.UpdateCollection();
}
private static void ItemsSourceChanged(object sender, DependencyPropertyChangedEventArgs args)
{
var element = sender as CollectionPropertyBehavior;
if (element == null || element.ItemsSource == null) return;
element.ItemsSourceChanged();
}
private void ItemsSourceChanged()
{
this.proxies = null;
if (this.Items == null || !this.Items.Any() || this.CollectionPropertyPath == null) return;
// Cria os proxies
this.proxies = this.Items.Select(o =>
{
var proxy = new ValueProxy();
proxy.Bind(o, this.CollectionPropertyPath);
proxy.ValueChanged += (s, e) => this.UpdateSource();
return proxy;
}).ToArray();
this.UpdateSource();
}
private void UpdateSource()
{
if (this.syncking) return;
// Atualiza o valor
using (new SynckingScope(this))
{
object value = this.proxies.First().Value;
foreach (var proxy in this.proxies.Skip(1))
{
value = object.Equals(proxy.Value, value) ? value : this.DefaultValue;
}
this.Value = value;
}
}
private void UpdateCollection()
{
// Se o valor estiver mudando em função da atualização de algum
// elemento da coleção, não faz nada
if (this.syncking) return;
using (new SynckingScope(this))
{
// Atualiza todos os elementos da coleção,
// atrávés dos proxies
if (this.proxies != null)
foreach (var proxy in this.proxies)
proxy.Value = this.Value;
}
}
protected override void OnAttached()
{
base.OnAttached();
// Bind da propriedade do objeto fonte para o behavior
var binding = new Binding(this.SourcePropertyPath);
binding.Source = this.AssociatedObject;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(this, ValueProperty, binding);
}
protected override void OnDetaching()
{
base.OnDetaching();
// Limpa o binding de value para a propriedade do objeto associado
this.ClearValue(ValueProperty);
}
internal class SynckingScope : IDisposable
{
private readonly CollectionPropertyBehavior parent;
public SynckingScope(CollectionPropertyBehavior parent)
{
this.parent = parent;
this.parent.syncking = true;
}
public void Dispose()
{
this.parent.syncking = false;
}
}
internal class ValueProxy : DependencyObject
{
public event EventHandler ValueChanged;
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(ValueProxy), new PropertyMetadata(null, OnValueChanged));
private static void OnValueChanged(object sender, DependencyPropertyChangedEventArgs args)
{
var element = sender as ValueProxy;
if (element == null || element.ValueChanged == null) return;
element.ValueChanged(element, EventArgs.Empty);
}
public void Bind(object source, string path)
{
// Realiza o binding de value com o objeto desejado
var binding = new Binding(path);
binding.Source = source;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(this, ValueProperty, binding);
}
}
}
这种方法的优点是,它是完全可重用。在这个例子中,我们用它来处理选择,但是你可以在你的ItemViewModel中绑定到一个ComboBox的头部等等。
行为是从我的Silverlight 4项目移植过来的,但我测试过它在WPF应用程序中正常工作。不过,我认为在WPF中,我们可能会找到一个更好的方法来将行为调整为MarkupExtension。如果我有时间的话,我可以看看。此外,还可以对其进行调整,以便可以将选定项绑定到SelectedItems,当有选定项目时,会更新它们,如果没有,则会更新全部项目。
相关问题
- 1. 复选框DataGrid中MVVM WPF
- 2. wpf datagrid复选框列
- 3. 复选框在WPF Datagrid中排序时
- 4. WPF Datagrid的复选框NotifyOnTargetUpdated不工作
- 5. 不能DataGrid中的WPF C#访问复选框
- 6. 使用WPF中的Datagrid复选框的多选择
- 7. WPF Toolkit DataGrid复选框问题
- 8. 如何在Datagrid WPF中添加复选框c#
- 9. 在WPF中的Xceed Datagrid中创建一个复选框
- 10. datagrid中的itemrendrer复选框
- 11. 用Xceed的WPF DataGrid中的图像替换复选框
- 12. Flex的复选框DataGrid中
- 13. C#WPF取消选中复选框
- 14. HTML应用程序“复选框”响应
- 15. 复选框像radiobutton wpf c#
- 16. 着色wpf复选框C#
- 17. 选择所有WPF DataGrid的复选框只选择鉴于
- 18. 在DataGrid中复选框
- 19. WPF - Datagrid中的复选框设置行的背景颜色
- 20. WPF数据绑定的复选框失败DataGrid中
- 21. DataGrid复选框无法选中
- 22. 将c#WPF复选框绑定到应用程序设置和更新设置
- 23. 列表框和复选框 - XAML/C# - Windows 8应用程序
- 24. Datagrid复选框样式
- 25. 获取datagrid中复选框的值
- 26. WPF单击写保护的DataGrid上的复选框
- 27. Datagrid复选框单元格
- 28. Wpf复合应用程序
- 29. 如何在使用WPF选中datagrid中的复选框时获取行值?
- 30. c#datagrid复选框多删除