[当数据网格行失去焦点而不是要求用户按回车键来提交时,如何强制提交?
我有一个MVVM项目,其主DataGrid
使用的RowDetailsTemplate
包含另一个子DataGrid
。它使用在行上按“ Enter”的默认行为来提交值更改。我为主行和子行都实现了ValidatonRule
。
Transaction ValdationStep.CommittedValue
。SubtransactionValidation ValdationStep.CommittedValue
。Transaction ValdationStep.CommittedValue
被触发。然后,当选择一个新帐户时(导致ItemsSource
集合发生更改),CollectionChanged
上会触发一个ItemsSource
事件,以删除源项目(未提交的交易),就像用户点击了“ Esc”一样。[我假设CollectionChanged
事件是由DataGrid
决定尚未提交的行触发的,因此将其从集合中删除。CollectionChanged
和删除项目的一种方法,但似乎更需要强制提交更改。另外,我必须弄清楚何时启用/禁用何时忽略事件。[我以为这个SO: wpf Datagrid force datagrid row evaluation可能是一个解决方案(虽然过大了),并在按钮代码中实现了它(请参见下文),但是当我选择其他帐户和[ C0]集合已更改。
CollectionChanged
然后我尝试捕获ItemsSource
(我发现该事件是在单击[Subs]按钮后触发的)并在该行上强制private void ToggleSubs_Click(object sender, RoutedEventArgs e)
{
...
foreach (var item in BankDataGrid.ItemContainerGenerator.Items)
{
var container = BankDataGrid.ItemContainerGenerator.ContainerFromItem(item);
if (container != null && container is DataGridRow dgr)
{
dgr.BindingGroup.CommitEdit();
}
}
}
。但是,当我选择其他帐户时,再次触发了ValidationStep.ConvertedProposedValue
事件以删除该项目。
XAML
BindingGroup.CommitEdit()
MainVM
CollectionChanged
用于交易收集的AccountVM CollectionChanged处理程序
<Grid>
<Grid x:Name="MainPanel">
<Grid.RowDefinitions>
<RowDefinition Height="26" />
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
...
<Grid x:Name="Controls" Grid.Row="1" >
...
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Left">
<Label Content="Account" VerticalAlignment="Center" />
<ComboBox Name="ControlsAccount" VerticalAlignment="Center" Width="210"
ItemsSource="{Binding AccountList}"
SelectedItem="{Binding SelectedAccount}"
IsEnabled="{Binding HasAccounts}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
Foreground="{Binding ItemForeColor}"
Background="{Binding ItemBackColor}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
...
</Grid>
<DataGrid x:Name="BankDataGrid" Grid.Row="2"
ItemsSource="{Binding SelectedAccount.Transactions, UpdateSourceTrigger=LostFocus}"
SelectedItem="{Binding SelectedAccount.SelectedTransaction, Converter={StaticResource TransConverter}}" >
...
<DataGrid.RowValidationRules>
<valid:BankTransactionValidation ValidationStep="UpdatedValue" />
<valid:BankTransactionValidation ValidationStep="CommittedValue" />
</DataGrid.RowValidationRules>
...
<DataGrid.Columns>
...
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate x:Name="SubDataTemplate">
<DataGrid x:Name="SubDataGrid"
ItemsSource="{Binding Subtransactions}"
SelectedItem="{Binding SelectedSubtransaction, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource SubtransConverter}}" >
...
<DataGrid.RowValidationRules>
<valid:SubtransactionValidation ValidationStep="UpdatedValue" />
<valid:SubtransactionValidation ValidationStep="CommittedValue" />
</DataGrid.RowValidationRules>
...
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
...
</Grid>
BankTransactionValidation
partial class MainVM : BaseVM
{
public MainVM()
{
LoadSettings();
InitMainPanel();
InitTransactionSearch();
InitLookupMaintenance();
InitLookupReplacement();
InitAccountDetails();
InitBusyPanel();
}
...
private ObservableCollection<AccountVM> accountList;
public ObservableCollection<AccountVM> AccountList
{
get => accountList;
set
{
accountList = value;
NotifyPropertyChanged();
}
}
private AccountVM selectedAccount;
public AccountVM SelectedAccount
{
get => selectedAccount;
set
{
selectedAccount = value;
NotifyPropertyChanged();
if (selectedAccount != null)
{
WindowTitle = $"{selectedAccount.Name} - {AppName}";
BankDataGridVisibility = VISIBILITY_SHOW;
BackgroundImageVisibility = VISIBILITY_HIDE;
SubtransactionsVisibility = VISIBILITY_COLLAPSE;
SubtransactionVM.XferAccountRemove(selectedAccount.Name, AccountList);
}
else
{
HideTransactions();
}
HasAccounts = (AccountList != null && AccountList.Count > 0) ? LITERAL_TRUE : LITERAL_FALSE;
}
}
...
}
当数据网格行失去焦点而不是要求用户按回车键进行提交时,如何强制提交?我有一个使用RowDetailsTemplate的带有主DataGrid的MVVM项目,它具有...
public class BankTransactionValidation : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var result = ValidationResult.ValidResult;
var bg = (BindingGroup)value;
var row = (DataGridRow)bg.Owner;
if (row.Item is BankTransactionVM item)
{
switch (ValidationStep)
{
case ValidationStep.RawProposedValue:
break;
case ValidationStep.ConvertedProposedValue:
break;
case ValidationStep.UpdatedValue:
break;
case ValidationStep.CommittedValue:
if (item.TransactionId > 0)
{
item.Update();
if (item.Subtransactions.Count == 0)
{
item.Subtransactions.Add(new SubtransactionVM(item.TransactionId));
}
}
break;
}
}
return result;
}
}