Fragen zum DataBinding - fehlende Eigenschaft

  • WPF

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von MasterQ.

    Fragen zum DataBinding - fehlende Eigenschaft

    Hallo,

    ich habe ein UserControl ​ImageZoomMove erstellt und in ein Fenster ​WndImage eingebunden.

    XML-Quellcode

    1. ​ <ctrl:ImageZoomMove SourceImageZoomMove="{Binding SourceWnd}"/>


    Aus dem XML-Schippsel liest man, dass ​WndImage eine Eigenschaft ​SourceWnd hat und ​ImageZoomMove eine Abhängigkeits-Eigenschaft ​SourceImageZoomMove.

    Wenn ich die Anwendung starte erhalte ich einen Bindungsfehler mit der Beschreibung:

    ​Die Eigenschaft "SourceWnd" wurde im Objekt vom Typ "ImageZoomMove" nicht gefunden.

    Ähem, warum sollte ​ImageZoomMove eine Eigenschaft ​SourceWnd haben?

    Gruß

    MQ
    Hallo

    Wie wurde bzw. auf was wurde denn der Datenkontext des überliegenden Controls festgelegt.

    Etwas mehr infos brauchen wir da schon.

    Zumindestens: Info wie und auf was der Datenkontext festgelegt ist.

    Im Idealfall:

    Den XAML und Code des Controls in dem sich der Schnipsel den du gepostet hast befindet.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Das selbst erstellte Steuerelement ist recht einfach gestrickt:

    Spoiler anzeigen


    XML-Quellcode

    1. ​<UserControl x:Class="DSOHelfer.Controls.ImageZoomMove"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:local="clr-namespace:DSOHelfer.Controls"
    7. mc:Ignorable="d"
    8. d:DesignHeight="450"
    9. d:DesignWidth="800"
    10. DataContext="{Binding RelativeSource={RelativeSource Self}}"
    11. >
    12. <Grid>
    13. <Canvas SizeChanged="Canvas_SizeChanged">
    14. <Image Name="image"
    15. MouseDown="image_MouseDown"
    16. MouseUp="image_MouseUp"
    17. MouseWheel="image_MouseWheel"
    18. MouseMove="image_MouseMove"
    19. Width="auto"
    20. Height="auto"
    21. Stretch="Uniform"
    22. />
    23. </Canvas>
    24. </Grid>
    25. </UserControl>



    Mit folgendem Code (gekürzt)

    C#-Quellcode

    1. public partial class ImageZoomMove :UserControl {
    2. public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( "SourceImageZoomMove", typeof(string), typeof(ImageZoomMove));
    3. public string SourceImageZoomMove {
    4. get { return (string)GetValue(SourceProperty); }
    5. set {
    6. if ((string)GetValue(SourceProperty) != value) {
    7. SetValue( SourceProperty, value);
    8. //NotifyPropertyChanged();
    9. image.Source = new BitmapImage(new Uri(value,UriKind.RelativeOrAbsolute));
    10. }
    11. }
    12. }
    13. public ImageZoomMove() {
    14. InitializeComponent();
    15. }
    16. ...
    17. }





    Und das Fenster, das das Steuerelement verwendet:

    Spoiler anzeigen


    XML-Quellcode

    1. ​<Window x:Class="DSOHelfer.Forms.WndImage"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:DSOHelfer.Forms"
    7. xmlns:ctrl="clr-namespace:DSOHelfer.Controls"
    8. DataContext="{Binding RelativeSource={RelativeSource Self}}"
    9. mc:Ignorable="d"
    10. Title="Karte"
    11. Height="450"
    12. Width="800"
    13. >
    14. <Grid>
    15. <Grid.RowDefinitions>
    16. <RowDefinition Height="*"/>
    17. <RowDefinition Height="auto"/>
    18. </Grid.RowDefinitions>
    19. <ctrl:ImageZoomMove Grid.Row="0"
    20. x:Name="imageZoomMove"
    21. SourceImageZoomMove="{Binding SourceWnd}"/> <!-- hier meckert der Compiler mit der im ersten Post beschriebenen Beschreibung -->
    22. <ToolBar Grid.Row="1">
    23. <TextBlock Text="{Binding ToolText}" FontSize="16"/>
    24. </ToolBar>
    25. </Grid>
    26. </Window>



    mit

    C#-Quellcode

    1. public partial class WndImage :Window, INotifyPropertyChanged {
    2. string _toolText = "Hello World!";
    3. public string ToolText {
    4. get { return _toolText; }
    5. set {
    6. if (_toolText != value) {
    7. _toolText = value;
    8. NotifyPropertyChanged();
    9. }
    10. }
    11. }
    12. public event PropertyChangedEventHandler PropertyChanged;
    13. private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") {
    14. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    15. }
    16. string _source;
    17. public string SourceWnd {
    18. get { return _source; }
    19. set {
    20. if (_source != value){
    21. _source = value;
    22. imageZoomMove.SourceImageZoomMove = value;
    23. ToolText = value;
    24. NotifyPropertyChanged();
    25. }
    26. }
    27. }
    28. public WndImage(string imagesource) {
    29. InitializeComponent();
    30. SourceWnd = imagesource;
    31. }
    32. }





    Ich kämpfe mit dem DataBinding und daher ist in der set-Mehode von WndSource etwas Gebastelei. Im Moment ist aber erst die Frage offen, wie ich das (komplette) Steuerelement and die Eigenschaft des Hauptfensters binde. Wie ich dann innerhalb des Steuerelementes die Eigenschaft ​ImageSoureZoomMove and die Eigenschaft Source des Image binde folgt dann. Irgendwie hat das gestern nicht geklappt.
    Hallo

    Zum einen ist der Setter eines DependencyProperties Tabu.
    Bei DP muss man immer mit SetValue() den Wert setzen und mittels GetValue() abrufen. Ich habe bez. DP auch ein eigens Kapitel in meiner Tutorialreihe wo ich darauf eingehe warum und weshalb.

    Was den Datenkontext angeht setze doch mal explizit in deinem Konstruktor des WndImage den DataContext. DataContext = this

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Zum einen ist der Setter eines DependencyProperties Tabu.

    Was meinst du damit? Ohne Setter ist das Ding doch meist nutzlos.

    Im Prinzip habe ich es bei meinem Projekt so umgesetzt, wie du es im Tutorial beschreibst. Beschrieben wird aber leider nur, wie ich eine Eigenschaft des UserControls an seine Unterelemente weitergebe. Und das funktioniert bei mir.

    Es kneift an der Stelle, eine Eigenschaft eines Elementes (hier Hauptfenster) an sein untergeordnetes UserControl zu binden. Ich verstehe nicht, warum die Eigenschaft WndSource des Hauptfensters in dem UserControl ImageZoomMove überhaupt gesucht wird.

    Es gibt hier 3 Ebenen


    WndImage

    XAML: <ImageZoomMove
    x:Name="imageZoomMove"
    SourceImageZoomMove="{Binding SourceWnd}"/>


    =>


    ImageZoomMove

    XAML: <Image Name="image"
    Source="{Binding SourceImageZoomMove, Converter={StaticResource imageSourceConverter}}"


    =>


    Image


    Property (SourceWnd)
    Dependency Property (SourceImageZoomMove)
    Dependency Property (Image.Source)
    string
    string
    ImageSource


    Das Binden von der Eigenschaft SourceWnd an die Abhängigkeits-Eigenschaft SourceImageZoomMove des Steuerelements ImageZoomMove ist doch das was man tagtäglich macht, wenn auch meist nicht mit selbst erstellten Controls. Ich mache das nicht anders als mit der ToolBox des Hauptfensters. Und dennoch erhalte ich einen Bindungsfehler.


    System.Windows.Data Error: 40 : BindingExpression path error: 'SourceWnd' property not found on 'object' ''ImageZoomMove' (Name='imageZoomMove')'. BindingExpression:Path=SourceWnd; DataItem='ImageZoomMove' (Name='imageZoomMove'); target element is 'ImageZoomMove' (Name='imageZoomMove'); target property is 'SourceImageZoomMove' (type 'String')

    Hier scheint was mit den DataContext nicht zu stimmen. In allen Elementen setze ich den DataContext auf this, bzw. Self mit DataContext="{Binding RelativeSource={RelativeSource Self}}"

    Aber was sollte damit falsch sein?

    Was den Datenkontext angeht setze doch mal explizit in deinem Konstruktor des WndImage den DataContext. DataContext = this

    Das hatte ich schon ausprobiert, bringt leider nix.


    EDIT:

    XML-Quellcode

    1. <ctrl:ImageZoomMove Grid.Row="0"
    2. x:Name="imageZoomMove"
    3. SourceImageZoomMove="{Binding SourceWnd, ElementName=Isch}"/>


    Ich habe dem Hauptfenster einen Namen ("Isch") gegeben und im Aufruf des Controls explizit den Datenkontext gesetzt. Und siehe da, jetzt bleibt der Bindungsfehler aus.

    Jetzt bleibt die Frage ,warum ich hier ElementName angeben muss, bei ToolBar aber nicht.

    XML-Quellcode

    1. <ToolBar Grid.Row="1"> <TextBlock Text="{Binding ToolText}" FontSize="16"/> </ToolBar>


    ?

    Gruß

    MQ

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MasterQ“ ()