wpf - 使用自定义 ICommand 实现验证按钮单击时的网格行 - WPF
问题描述
我想验证我的DataGrid
行是否有错误,如果存在任何错误,则应该禁用“保存”按钮,或者至少应该有一些消息说有错误。
经过一些研究,我偶然发现了以下帖子:检测 WPF 验证错误
该帖子作为解决方案使用这段代码来验证 DataGrid 的错误:
private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = IsValid(sender as DependencyObject);
}
private bool IsValid(DependencyObject obj)
{
// The dependency object is valid if it has no errors and all
// of its children (that are dependency objects) are error-free.
return !Validation.GetHasError(obj) &&
LogicalTreeHelper.GetChildren(obj)
.OfType<DependencyObject>()
.All(IsValid);
}
但是,我正在ICommand
为我的按钮使用实现,我似乎无法弄清楚如何IsValid
用它来实现该功能。我尝试了几件事来注册DependencyObject
,使用 aBinding
和其他一些东西。
谁能指出我正确的方向,我想这应该很简单,但我无法理解它。
下面是我的按钮的实现:
public class MyViewModel
{
public ICommand MyCommandButton { get; set; }
public MyViewModel()
{
MyCommandButton = new BaseCommand(MyCommandFunction);
this.Initialize();
}
private void MyCommandFunction(object obj)
{
//... some (not yet implemented) logic
}
public class BaseCommand : ICommand
{
private Predicate<object> _canExecute;
private Action<object> _method;
public event EventHandler CanExecuteChanged;
public BaseCommand(Action<object> method)
: this(method, null)
{
}
public BaseCommand(Action<object> method, Predicate<object> canExecute)
{
_method = method;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_method.Invoke(parameter);
}
}
}
XAML 按钮:
<Button
Name="MyButton"
Command="{Binding MyCommandButton}"
/>
更新
经过更多的研究(@RajN 示例中的每次都返回Object parameter
),我偶然发现了以下帖子:object sender always is null in RelayCommand声明我应该使用for it not to be 。现在该函数可以工作,但即使在.MyCommandCanExecuteFunction
null
CommandParameter
null
IsValid
datagrid
我怀疑数据网格/数据本身有问题,所以我也会在下面发布:
数据网格
<DataGrid x:Name="MainGrid"
ItemsSource="{Binding ItemList}"
SelectedItem="{Binding SelectedItem,Converter={StaticResource ignoreNewItemPlaceHolderConverter}}"
AutoGenerateColumns="False"
DataContextChanged="OnMainGridDataContextChanged"
CanUserAddRows="False"
>
<DataGrid.Columns>
<DataGridTextColumn>
<DataGridTextColumn.Header>
<Grid Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
</Grid.ColumnDefinitions>
<Button
Height="25"
Width="25"
Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}"
Command="{Binding Path=DataContext.AddRowCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
ToolTip="Voeg regel toe"
>
<materialDesign:PackIcon
Kind="Add"
Height="24"
Width="24" />
</Button>
</Grid>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding SequenceNumber}"
Header="Line"
EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnEditingStyle}"
Width="63"
IsReadOnly="true" />
<DataGridTextColumn Header="Width" Width="100" IsReadOnly="false" EditingElementStyle="{StaticResource errTemplate}" >
<DataGridTextColumn.Binding>
<Binding Path="Width" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<validationbinding1:RequiredRule ValidatesOnTargetUpdated="True"/>
<validationbinding1:NumericRule ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Height" Width="100" IsReadOnly="false" EditingElementStyle="{StaticResource errTemplate}" >
<DataGridTextColumn.Binding>
<Binding Path="Height" ValidatesOnDataErrors="True" NotifyOnValidationError = "True">
<Binding.ValidationRules>
<validationbinding1:RequiredRule />
<validationbinding1:NumericRule />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
~~Some other columns which are left out
</DataGrid.Columns>
</DataGrid>
DataGrid 属性和绑定:
关于视图本身
private void OnMainGridDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
m_MyViewModel = (m_MyViewModel)this.DataContext;
}
在视图模型中
public class MyViewModel : MyModel
{
// Property variables
private ObservableCollection<ItemListDetails> p_ItemList;
public ICommand MyCommandButton { get; set; }
public MyViewModel()
{
MyCommandButton = new BaseCommand(MyCommandFunction, canExecute);
this.Initialize();
}
private bool canExecute (object obj)
{
return IsValid(obj as DependencyObject);
}
private bool IsValid(DependencyObject obj)
{
// The dependency object is valid if it has no errors and all
// of its children (that are dependency objects) are error-free.
if (obj == null)
return true;
return !Validation.GetHasError(obj) &&
LogicalTreeHelper.GetChildren(obj)
.OfType<DependencyObject>()
.All(IsValid);
}
private void MyCommandFunction(object obj)
{
//... some (not yet implemented) logic
}
private void AddRow(object obj)
{
ItemListDetails Item = new ItemListDetails
{
Width = 0,
Height = 0,
};
p_ItemList.Add(Item);
}
public ObservableCollection<ItemListDetails> ItemList
{
get { return p_ItemList; }
set
{
p_ItemList = value;
this.MutateVerbose(ref p_ItemList, value, RaisePropertyChanged());
}
}
/// <summary>
/// The currently-selected item.
/// </summary>
public ItemListDetails SelectedItem { get; set; }
/// <summary>
/// Updates the ItemCount Property when the list collection changes.
/// </summary>
void OnListChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// Update item count
this.ItemCount = this.p_ItemList.Count;
// Resequence list
SequencingService.SetCollectionSequence(this.p_ItemList);
}
/// <summary>
/// Initializes this application.
/// </summary>
private void Initialize()
{
// Create item list
p_ItemList = new ObservableCollection<ItemListDetails>();
// Subscribe to CollectionChanged event
p_ItemList.CollectionChanged += OnListChanged;
// Initialize list index
this.p_ItemList = SequencingService.SetCollectionSequence(this.p_ItemList);
// Update bindings
//base.RaisePropertyChangedEvent("GroceryList");
//this.MutateVerbose(ref _materiaal, value, RaisePropertyChanged());
}
}
DataGrid 项的 ItemListDetails 类
public class ItemListDetails : ObservableObject, ISequencedObject
{
// Property variables
private int p_SequenceNumber;
private int p_Width;
private int p_Height;
/// <summary>
/// Default constructor
/// </summary>
public ItemListDetails ()
{
}
/// <summary>
/// Paramterized constructor.
/// </summary>
public ItemListDetails (int width, int height, int itemIndex)
{
p_Width = width;
p_Height = height;
p_SequenceNumber = itemIndex;
}
/// <summary>
/// The sequential position of this item in a list of items.
/// </summary>
public int SequenceNumber
{
get { return p_SequenceNumber; }
set
{
p_SequenceNumber = value;
base.RaisePropertyChangedEvent("SequenceNumber");
}
}
/// <summary>
/// The width
/// </summary>
public int Width
{
get { return p_Width; }
set
{
p_Width = value;
base.RaisePropertyChangedEvent("Int");
}
}
/// <summary>
/// The height
/// </summary>
public int Height
{
get { return p_Height; }
set
{
p_Height = value;
base.RaisePropertyChangedEvent("Int");
}
}
}
该类MyModel
包含一些其他字段,这些字段不包含在DataGrid
.
解决方案
干得好
public class MyViewModel
{
public ICommand MyCommandButton { get; set; }
public MyViewModel()
{
MyCommandButton = new BaseCommand(MyCommandFunction, MyCommandCanExecuteFunction);
this.Initialize();
}
private void MyCommandFunction(object obj)
{
//... some (not yet implemented) logic
}
private bool MyCommandCanExecuteFunction(object obj)
{
return IsValid(obj as DependencyObject);
}
private bool IsValid(DependencyObject obj)
{
// The dependency object is valid if it has no errors and all
// of its children (that are dependency objects) are error-free.
return !Validation.GetHasError(obj) &&
LogicalTreeHelper.GetChildren(obj)
.OfType<DependencyObject>()
.All(IsValid);
}
}
推荐阅读
- c++ - 如何使用二维数组创建游戏地图?
- c - fpic 和 O3 优化标志
- c++ - 使用地图
而不是矢量 避免指针失效 - c++ - Is it safe to cast between a function pointer and a member function pointer?
- jquery - How to create nested elements with classes inside li using jQuery
- python - Need to throttle scraper to only hit website every 4s from a python list of URLS - scraperapi, scrapy, python
- python - How can I make my script wait for input for a set amount of time
- python - 对于这些 Google 库,我在 App Engine 上缺少哪些要求?
- python - 熊猫使用 groupby 并根据各种条件删除重复项
- javascript - 对于使用数组内容创建的循环输入,在检查时添加数据但不在浏览器中显示