[ad_1]
私は WPF/EF を初めて使用しており、シンプルなマスター詳細 UI を持っています。 検証ルールを使用して単純なセル/行検証を実装しました。 詳細データの整数フィールドを検証する必要があります。つまり、すべてのデータグリッド行に対して検証します。 データグリッドレベルとページ(これはXAPAPアプリケーションです)グリッドレベルでバインディンググループを実装しようとしました。 さまざまなプロパティなどを設定します。[保存]ボタンをクリックすると検証ルールが起動しますが、バインディング グループには項目がありません。 インターネットで調べましたが、やりたいことに関する参考資料が 1 つ見つかりました。 解決策は私にはうまくいきませんでした。
1) フィールドの複数の行を検証するにはどうすればよいですか?
2) 誰かが簡単な例を提供してもらえますか?
誰かが見る必要がある場合は、XAML、コードビハインド、バインディンググループ検証ルールを含めるようにします。 注: 私は初心者なので、MVVM アプローチを実装していません。 マスター/詳細 UI へのアプローチは、WPF/EF に関する MSDN オンライン ビデオ (Beth Massie 著) から引用されています。
TIA
— バインディング グループの検証ルール (データ グループ上)
public class UtilizationValidationRule : ValidationRule { // for Utilization Entry public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { // the UtilizationAmount total cannot > 100% BindingGroup bindingGroup = (BindingGroup)value; if (bindingGroup != null) { // utilization total int utilTotal = 0; foreach (var bindingSource in bindingGroup.Items) { // get item Utilization util = (Utilization)bindingSource; utilTotal += util.UtilizationAmount; } if (utilTotal > 100) { return new ValidationResult(false, "Total utilization cannot exceed 100%."); } } return new ValidationResult(true, null); } }
— 確認する必要がある場合は、背後のコードをここに示します。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using DataModel; using System.ComponentModel; namespace WorkbookPlan { /// <summary> /// Interaction logic for page /// </summary> public partial class UtilizationEntry2 : Page { // NOTE: The Master-Detail UIs are different than those that use just // fields for data entry and use the EF entity IDataErrorInfo interface // for validation // Seemingly the Detail collection does not fire the EF entity class // I am not sure why. Hence for validation must be done by validation rules // at a row/column level. private WorkbookPlanEntities db = new WorkbookPlanEntities(); private EmpUtilCollection EmpUtilData; // collections for EF data private CollectionViewSource MasterViewSource; private CollectionViewSource DetailViewSource; // collections wired to UI private ListCollectionView MasterView; private BindingListCollectionView DetailView; public UtilizationEntry2() { InitializeComponent(); } private void Page_Loaded(object sender, RoutedEventArgs e) { try { // get data from model var employees = from emp in db.Employees.Include("Utilizations") orderby emp.LastName, emp.FirstName select emp; CollectionViewSource organizationLookup = (CollectionViewSource)this.FindResource("OrganizationLookup"); // lookup organizationLookup.Source = from org in db.Organizations orderby org.Name select org; // create obs. collection of data from EF data context this.EmpUtilData = new EmpUtilCollection(employees, db); // set up Master view: Employees which is read only since we are not changing Employee table this.MasterViewSource = (CollectionViewSource)this.FindResource("MasterView"); // set up detail view: Utilization which will be changed this.DetailViewSource = (CollectionViewSource)this.FindResource("DetailView"); this.MasterViewSource.Source = this.EmpUtilData; this.MasterView = (ListCollectionView)(MasterViewSource.View); this.MasterView.CurrentChanged += new EventHandler(MasterView_CurrentChanged); this.DetailView = (BindingListCollectionView)(DetailViewSource.View); } catch (Exception ex) { MessageBox.Show("Exception: " + ex.Message); } } void MasterView_CurrentChanged(object sender, EventArgs e) { this.DetailView = (BindingListCollectionView)(DetailViewSource.View); // set navigation buttons // this.PreviousClick.IsEnabled = this.MasterView.CurrentPosition > 0; //this.NextClick.IsEnabled = this.MasterView.CurrentPosition < this.MasterView.CurrentPostion - 1; } private void SaveClick(object sender, RoutedEventArgs e) { try { bool okay = this.FormBindingGroup.ValidateWithoutUpdate(); if (okay) { db.SaveChanges(); MessageBox.Show("Data was saved.", this.Title, MessageBoxButton.OK, MessageBoxImage.Information); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void AddClick(object sender, System.Windows.RoutedEventArgs e) { // for detail only this.DetailView.AddNew(); this.DetailView.CommitNew(); } private void DeleteClick(object sender, System.Windows.RoutedEventArgs e) { // for detail only if (this.DetailView.CurrentPosition > -1) { this.DetailView.RemoveAt(this.DetailView.CurrentPosition); } } private void PreviousClick(object sender, RoutedEventArgs e) { this.MasterView.MoveCurrentToPrevious(); } private void NextClick(object sender, RoutedEventArgs e) { this.MasterView.MoveCurrentToNext(); }
— XAML
<Page x:Class="WorkbookPlan.UtilizationEntry2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WorkbookPlan" xmlns:localuc="clr-namespace:UserControlLibrary;assembly=UserControlLibrary" mc:Ignorable="d" Title="Utilization Data Entry" Name="UtilizationEntry" Height="230" Width="600" Loaded="Page_Loaded"> <Page.Resources> <CollectionViewSource x:Key="OrganizationLookup"/> <CollectionViewSource x:Key="MasterView" /> <CollectionViewSource x:Key="DetailView" Source="{Binding Source={StaticResource MasterView}, Path='Utilizations'}"/> <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="Background" Value="LightSteelBlue"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush" Value="Black"/> <Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="Padding" Value="3" /> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style TargetType="{x:Type DataGridCell}"> <Style.Triggers> <Trigger Property="DataGridCell.IsSelected" Value="True"> <Setter Property="Background" Value="LightCyan" /> <Setter Property="Foreground" Value="Black" /> </Trigger> </Style.Triggers> </Style> <Style TargetType="{x:Type DataGridRow}"> <Setter Property="ValidationErrorTemplate"> <Setter.Value> <ControlTemplate> <Grid Margin="0,-2,0,-2" ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}"> <Ellipse StrokeThickness="0" Fill="Red" Width="{TemplateBinding FontSize}" Height="{TemplateBinding FontSize}" /> <TextBlock Text="!" FontSize="{TemplateBinding FontSize}" FontWeight="Bold" Foreground="White" HorizontalAlignment="Center" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Page.Resources> <Grid Name="FormGrid" > <Grid.ColumnDefinitions> <ColumnDefinition Width="300" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="5" /> <RowDefinition Height="25" /> <RowDefinition Height="5" /> <RowDefinition Height="100*" /> <RowDefinition Height="5" /> <RowDefinition Height="25" /> </Grid.RowDefinitions> <!--<Grid.BindingGroup> <BindingGroup x:Name="FormBindingGroup" NotifyOnValidationError="True" > <BindingGroup.ValidationRules> <local:UtilizationValidationRule ValidationStep="RawProposedValue" /> </BindingGroup.ValidationRules> </BindingGroup> </Grid.BindingGroup>--> <Border Grid.Row="0" BorderThickness="1" BorderBrush="Black" Grid.RowSpan="7" Grid.ColumnSpan="2" Background="White"></Border> <Border Grid.Row="0" Grid.ColumnSpan="3" BorderThickness="1" BorderBrush="Black" Background="Gainsboro"></Border> <localuc:PageHeader Grid.Row="0" Grid.ColumnSpan="2" Content="Utilization Data Entry"/> <Label Grid.Row="2" Grid.Column="0" Style="{StaticResource ListboxHeaderText}" VerticalContentAlignment="Center" >Employee List</Label> <localuc:DataEntryButtons x:Name="ucButtons" Grid.Row="2" Grid.Column="1" Save="SaveClick" Add="AddClick" Delete="DeleteClick"/> <Border Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="1" Style="{StaticResource BorderBlueBackground}"></Border> <Grid Grid.Row="4" Grid.Column="0" DataContext="{Binding Source={StaticResource MasterView}}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="80" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="5" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="25" /> <RowDefinition Height="5" /> <RowDefinition Height="30" /> <RowDefinition Height="5" /> <RowDefinition Height="30" /> <RowDefinition Height="5" /> <RowDefinition Height="30" /> </Grid.RowDefinitions> <localuc:NavigationButtons x:Name="ucNavigationButtons" Grid.Row="0" Grid.ColumnSpan ="2" Previous="PreviousClick" Next="NextClick"/> <Label Grid.Row="2" Grid.Column="0">Number:</Label> <Label Grid.Row="4" Grid.Column="0">Last Name:</Label> <Label Grid.Row="6" Grid.Column="0">First Name:</Label> <TextBox Grid.Row="2" Grid.Column="1" Padding="5" Name="Number" IsReadOnly="True" Text="{Binding Path=Number, Mode=OneWay}"/> <TextBox Grid.Row="4" Grid.Column="1" Padding="5" Name="LastName" IsReadOnly="True" Text="{Binding Path=LastName, Mode=OneWay}"/> <TextBox Grid.Row="6" Grid.Column="1" Padding="5" Name="FirstName" IsReadOnly="True" Text="{Binding Path=FirstName, Mode=OneWay}"/> </Grid> <Border Grid.Row="4" Grid.Column="1" BorderThickness="1" BorderBrush="Black" Background="White"> <DataGrid Grid.Row="4" Grid.Column="1" Name="ListView1" AutoGenerateColumns="false" CanUserAddRows="false" CanUserDeleteRows="false" GridLinesVisibility="All" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource DetailView}}" Background="LightGray" BorderBrush="Cornsilk" > <DataGrid.BindingGroup> <BindingGroup x:Name="FormBindingGroup" NotifyOnValidationError="True" > <BindingGroup.ValidationRules> <local:UtilizationValidationRule ValidationStep="RawProposedValue" /> </BindingGroup.ValidationRules> </BindingGroup> </DataGrid.BindingGroup> <DataGrid.Resources> <Style x:Key="errorStyle" TargetType="{x:Type TextBox}"> <Setter Property="Padding" Value="-2"/> <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="BorderThickness" Value="2"/> <Setter Property="BorderBrush" Value="red"/> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers> </Style> </DataGrid.Resources> <DataGrid.RowValidationRules> <local:UtilizationRowValidationRule ValidationStep="RawProposedValue"/> </DataGrid.RowValidationRules> <DataGrid.Columns> <DataGridComboBoxColumn Header="Organization" Width="150" ItemsSource="{Binding Source={StaticResource OrganizationLookup}}" SelectedValueBinding="{Binding Path=Organization, ValidatesOnExceptions=True,ValidatesOnDataErrors=True, NotifyOnValidationError=True,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name"> </DataGridComboBoxColumn> <DataGridTextColumn Header="Utilization" Width="75" EditingElementStyle="{StaticResource errorStyle}"> <DataGridTextColumn.Binding> <Binding Path="UtilizationAmount" NotifyOnValidationError="true" UpdateSourceTrigger="PropertyChanged" ValidatesOnExceptions="true" ValidatesOnDataErrors="true"> <Binding.ValidationRules> <local:PercentValidationRule/> </Binding.ValidationRules> </Binding> </DataGridTextColumn.Binding> </DataGridTextColumn> </DataGrid.Columns> </DataGrid> </Border> <ListView Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding Path=(Validation.Errors), ElementName=FormGrid}"> <ListView.ItemTemplate> <DataTemplate> <Label Foreground="Red" Content="{Binding Path=ErrorContent}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Page>
[ad_2]
コメント