Laden...

Datagrid Raw Validierung verschwindet nicht

Erstellt von dila71 vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.199 Views
D
dila71 Themenstarter:in
103 Beiträge seit 2005
vor 5 Jahren
Datagrid Raw Validierung verschwindet nicht

Hallo,
ich habe folgendes Datagrid:

<DataGrid x:Name="tagsGrid" ItemsSource="{Binding}" GridLinesVisibility="Vertical" AlternatingRowBackground="#C3DDE5" 
                             AutoGenerateColumns="False" CanUserAddRows="True" IsReadOnly="False" 
                             SelectionUnit="Cell" SelectionMode="Extended" BorderThickness="3" RowStyle="{StaticResource RawTagDataGridRow}">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="TagName" Header="Tag" Width="*" KeyboardNavigation.TabIndex="1"
                                    Binding="{Binding Mode=TwoWay, Path=RawTag.TagName, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}"
                                    ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}" />
                <DataGridTextColumn x:Name="TagCycle" Header="Cycle" KeyboardNavigation.TabIndex="2"
                                    Binding="{Binding Mode=TwoWay, Path=RawTag.Cycle, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}" 
                                    ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}"/>
                <DataGridTextColumn x:Name="TagSource" Header="Source" Width="*" KeyboardNavigation.TabIndex="3"
                                    Binding="{Binding Mode=TwoWay, Path=RawTag.Source, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}"
                                    ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}"/>
                <DataGridTextColumn x:Name="Unassigned" Header="unassigned" Width="*" KeyboardNavigation.TabIndex="4"
                                    Binding="{Binding Mode=OneWay, Path=RawTag.Unassigned, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=False}"
                                    ElementStyle="{StaticResource ResourceKey=textBlockUnassignedStyle}"/>
                <DataGridTemplateColumn x:Name="editTagColumn" Header="" CanUserResize="True" KeyboardNavigation.TabIndex="5">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <WrapPanel>
                                <Button x:Name="btnTagDelete" Click="BtnTagDelete_Click" CommandParameter="{Binding}" Height="15" Width="15" Margin="2">
                                    <Button.Content>
                                        <Image Source="../Resources/delete.png"></Image>
                                    </Button.Content>
                                </Button>
                            </WrapPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

der verwendete RawTagDataGridRow - Style sieht folgendermaßen aus:

 <Style x:Key="RawTagDataGridRow" TargetType="{x:Type DataGridRow}">
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="FontFamily" Value="ArialMT"/>
        <Setter Property="Height" Value="Auto"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="true" >
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="BorderBrush" Value="Red"/>
                <Setter Property="IsEnabled" Value="True" />
                <Setter Property="ValidationErrorTemplate">
                    <Setter.Value>
                        <ControlTemplate>
                            <Grid>
                                <Border BorderBrush="red" BorderThickness="1" Background="#11FF0000" Opacity="0.5" IsHitTestVisible="False" x:Name="errorBorder"/>
                                <Ellipse Width="12" Height="12" Fill="Red" Stroke="Black" StrokeThickness="0.5"/>
                                <TextBlock FontWeight="Bold" Padding="4,0,0,0" Margin="0" VerticalAlignment="Top" Foreground="White" Text="!" ToolTip="{Binding RawTag.GetAllErrors}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="false" >
                <Setter Property="ToolTip" Value="{x:Null}"/>
                <Setter Property="BorderThickness" Value="0"/>
                <Setter Property="BorderBrush" Value="Green"/>
                <Setter Property="IsEnabled" Value="True" />
                <Setter Property="ValidationErrorTemplate" Value="{x:Null}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

der verwendete textBlockErrStyle - Style

<Style x:Key="textBlockErrStyle" TargetType="{x:Type TextBlock}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="false" >
                <Setter Property="ToolTip" Value="{x:Null}"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="true" >
                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                <Setter Property="Background" Value="Red" />
                <Setter Property="Foreground" Value="White" />
                <Setter Property="ToolTip" >
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource SimpleErrorConverter}">
                            <Binding Path="." RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}" />
                            <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=DataGridCell}" Path="Column"/>
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>

die im Viewmodel enthaltene Instanz Klasse RawTag implementiert INotifyDataErrorInfo

public Dictionary<string, List<string>> ErrorList = new Dictionary<string, List<string>>();
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

     
        public void NotifyErrorsChanged(string propertyName)
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }

        public bool HasErrors
        {
            get
            {
               return ErrorList.Count > 0;
            }
        }

        public void AddError(string propertyName, string error)
        {
            if (ErrorList.ContainsKey(propertyName))
            {
                if (!ErrorList[propertyName].Contains(error))
                {
                    ErrorList[propertyName].Add(error);
                }
            }
            else
            {
                ErrorList[propertyName] = new List<string>() { error };
            }

            NotifyErrorsChanged(propertyName);
        }

        public void RemoveError(string propertyName)
        {
           if (ErrorList.ContainsKey(propertyName))
            {
                ErrorList.Remove(propertyName);
                NotifyErrorsChanged(propertyName);
            }
        }

        public IEnumerable GetErrors(string propertyName)
        {
            ErrorList.TryGetValue(propertyName, out List<string> errorsForName);
            if (propertyName != "GetAllErrors")
            {
                OnPropertyChanged("GetAllErrors");
            }
            return errorsForName;
        }

        public string GetAllErrors
        {
            get
            {
                if (!HasErrors)
                {
                    return null;
                }

                int count = 1;
                var errorString = "Errors:";
                foreach (var e in ErrorList)
                {
                    e.Value.ForEach(v => errorString += Environment.NewLine + count++ + ". " + v);
                }
                return errorString;
            }
        }

die letzte Methode wird für den Tooltip der Row genutzt.
In den Properties wird das Interface verwendet, Bsp:

 public string TagName
        {
            get => tagName;
            set
            {
                if (value == tagName)
                {
                    return;
                }
                tagName = value;
                RemoveError("TagName");
                if (TagName.Contains(";"))
                {
                    AddError("TagName", "TagName may not contain the character ';'.");
                }
                if (TagName.Trim().Equals("?"))
                {
                    AddError("TagName", "'?' is not a valid value for TagName");
                }

                OnPropertyChanged();
            }
        }

Nun zu meinem Problem:

  1. Ich gehe in Zeile 1 in das Feld TagName und gebe ein ';' ein => die Zeile wird rot umrandet (wie im Style vorgegeben), das Ausrufezeichen laut Style erscheint, der Tooltip für die Zeile wird angezeigt. ≤ Gut, soll so sein
    2.a) Ich bleibe in Zeile 1 im Feld TagName und lösche das ';' => die Zeile wird nicht mehr rot umrandet (wie im Style vorgegeben), das Ausrufezeichen laut Style verschwindet, der Tooltip für die Zeile wird nicht mehr angezeigt. ≤ Gut, soll so sein
    2.b.1) Ich korrigiere nicht und verlasse das Feld TagName (egal ob in eine andere Zelle in der gleichen Zeile oder Wechsel in andere Zeile) => die Zelle wird zusätzlich rot hinterlegt und bekommt auch einen Tooltip ≤ Gut, soll so sein
    2.b.2) Ich gehe wieder in Zeile 1 in's Feld TagName und lösche das ';' => die Zeile bleibt rot umrandet, das Ausrufezeichen laut Style verschwindet nicht, der Tooltip für die Zeile wird weiter angezeigt. ≤ Schlecht
    2.b.3) Ich verlasse das Feld TagName (egal ob in eine andere Zelle in der gleichen Zeile oder Wechsel in andere Zeile) => die Zelle wird nicht mehr rot hinterlegt und hat auch keinen Tooltip mehr≤ Gut, soll so sein Die Zeile wird aber weiterhin als Fehlerhaft markiert (rot umrandet, Ausrufezeichen, Tooltip) Schlecht

Ich habe keine Ahnung, wo ich noch schauen kann.
Was habe ich vergessen / übersehen?

Viele Grüße und vielen Dank
Dirk