none
UpdateSourceTrigger von CustomControls updatet die Datenquelle nicht RRS feed

  • Frage

  • Ich arbeite derzeit mit WPF und C# an einer WPF-Applikation, in der die Controls und ihre Bindings zur Laufzeit in Code-behind erzeugt werden.
    Das WPF-Window auf dem ich die Controls erzeuge, hat ein ViewModel mit einer DataTable (die in DataContext eingestellt wird) und - am Fuss des WPF-Window - einen DataGrid, der an den DefaultView der DataTable gebunden ist.

    Zuerst verwendete ich zum Erzeugen von Controls die normalen WPF-Controls, z.B. die TextBox und die CheckBox.
    In deren Bindings setze ich UpdateSourceTrigger auf "PropertyChanged" wie hier:

    Binding controlBinding = new Binding(); controlBinding.Source =

    ViewModelContainer.viewmodel.ApplicationDataSet.Tables[BindingSource].DefaultView; controlBinding.Path = new PropertyPath("[0][" + BindingPath + "]"); controlBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;


    Wenn ich nach der Generierung der Controls den Text der TextBox änderte (ohne sie zu verlassen) oder die Checkbox an-/abhakte, konnte ich die Änderungen im DataGrid augenblicklich sehen.

    Nun aber verwende ich CustomControls die von den normalen WPF-Controls erben (um sie um neue Properties zu erweitern) und stelle leider fest, dass die UpdateSourceTrigger-Funktionalität nicht mehr arbeitet.
    Wenn ich den Text der TextBox ändere oder die Checkbox an-/abhake, sehe ich keine Änderung im DataGrid und damit ist auch keine Änderung in der gebundenen DataTable vorhanden.

    Wie man oben an meinem Codebeispiel sehen kann, tue ich bei meinen CustomControls Source bzw. DataContext auf die DataTable setzen.

    Ich vermute, dass ich an den Definitionen der CustomControls im Generic.xaml etwas ändern muss, aber was?

    Hier die Definitionen der CustomTextBox und der CustomCheckBox:

        <!--Style for the CustomControl CustomTextBox-->
        <Style TargetType="{x:Type local:CustomTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CustomTextBox}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <TextBox Text="{TemplateBinding Text}"
                                     TextWrapping="Wrap"
                                     HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                     VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                     ContextMenu="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomTextBox}},
                                Path=ContextMenu}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        <!--Style for the CustomControl CustomCheckBox-->
        <Style TargetType="{x:Type local:CustomCheckBox}" BasedOn="{StaticResource {x:Type CheckBox}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CustomCheckBox}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <CheckBox IsChecked="{TemplateBinding IsChecked}"
                                      HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                      VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                                <TextBlock Text="{TemplateBinding Text}"
                                           TextWrapping="Wrap"
                                           TextAlignment="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type CheckBox}},
                                    Path=HorizontalContentAlignment, Converter={StaticResource h2tAlignmentConverter}}"
                                           TextDecorations="{TemplateBinding TextDecorations}"/>
                            </CheckBox>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    Vielen Dank im voraus!

    Patrick

    Mittwoch, 18. Mai 2016 11:34

Alle Antworten

  • Hallo Patrick,

    Hast Du INotifyPropertyChanged sowohl im ViewModel als auch im Model implementiert? Vielleicht hilft Dir das Beispiel aus diesem Thread weiter.

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Donnerstag, 19. Mai 2016 11:31
    Moderator
  • Hallo Dimitar,

    Mein ViewModel ist lediglich ein Pseudo-ViewModel, das Daten nicht in Form von Properties enthält.

    Daher kann ich INotifyPropertyChanged nicht verwenden.

    Stattdessen habe ich in meinem ViewModel ein DataSet, das eine oder mehrere DataTables enthalten kann.

    Meine CustomControls können dank der zusätzlichen Eigenschaft "TableName", in der der Name der gebundenen DataTable steht, auf ihre Source zugreifen.

    Was mein Problem angeht, so habe ich für meine CustomTextBox und die CustomCheckBox bereits eine Lösung gefunden:

    <TextBox Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent},

    UpdateSourceTrigger=PropertyChanged}" [...]/>

    <CheckBox IsChecked="{Binding IsChecked, RelativeSource={RelativeSource

    TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"


    Bei einem weiteren CustomControl, das vom RadioButton erbt, gibt es allerdings noch Probleme.

    In meinem Fall habe ich eine Gruppe von RadioButtons mit demselben GroupName, die an verschiedene Felder eines Datensatzes gebunden sind (Typen sind bool, string, int).

    Der CustomRadioButton kann Daten aus der Datenbank richtig lesen und - Converter sei dank! - darstellen.

    Wenn ich aber auf einen der RadioButtons klicke, um den dazugehörenden Wert in der Source - also in dem aktuellen Datensatz - zu ändern, ist IsChecked am Ende immer FALSE.

    Kann ich irgendwas im ControlTemplate machen oder brauche ich einen speziellen Converter?

    Hier zum besseren Verständnis der Code von CustomRadioButton:

        <!--IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"-->
        <!--Style for the CustomControl CustomRadioButton-->
        <Style TargetType="{x:Type local:CustomRadioButton}" BasedOn="{StaticResource {x:Type RadioButton}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CustomRadioButton}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <RadioButton x:Name="innerRadioButton"
                                         IsChecked="{Binding IsChecked, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomRadioButton}}, UpdateSourceTrigger=PropertyChanged}"
                                         GroupName="{Binding GroupName, RelativeSource={RelativeSource TemplatedParent}}"
                                         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                                <TextBlock Text="{TemplateBinding Text}"
                                           TextWrapping="Wrap"
                                           TextAlignment="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type RadioButton}},
                                    Path=HorizontalContentAlignment, Converter={StaticResource h2tAlignmentConverter}}"
                                           TextDecorations="{TemplateBinding TextDecorations}"/>
                            </RadioButton>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    Donnerstag, 19. Mai 2016 13:12