Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Frage: Einfaches CustomControl mit Binding via DependencyProperty
N0ACE
myCSharp.de - Member



Dabei seit:
Beiträge: 5

Themenstarter:

Frage: Einfaches CustomControl mit Binding via DependencyProperty

beantworten | zitieren | melden

Hallo zusammen,

Ich habe ein CustomControl erstellt, welches im Prinzip ein einfacher TextBlock ist, dessen Inhalt ich via Bindung füttern will. Der XAML-Code sieht folgendermaßen aus:

<UserControl x:Class="TEST_Headlines.BaseHeadline"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             d:DesignHeight="50" d:DesignWidth="400"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">


    <Grid Background="Red">
        <Border/>
        <TextBlock Text="{Binding Title}"/>
    </Grid>
</UserControl>

Die CodeBehind-Datei enthält folgenden Code:


// using ...

namespace TEST_Headlines
{
    public partial class BaseHeadline : UserControl
    {
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
            "Title",
            typeof(string),
            typeof(BaseHeadline),
            null
        );
        
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public BaseHeadline()
        {
            InitializeComponent();
        }
    }
}


Dieses CustomControll erstelle ich und füge einen Verweis auf die DLL in ein neues Projekt. Das neue Projekt, welches dieses CustomControl nutzen soll, sieht so aus:

<UserControl x:Class="TEST_Libs_Testing_Components.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:TEST_Libs_Testing_Components"
             xmlns:H="clr-namespace:TEST_Headlines;assembly=TEST_Headlines"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="400">
    
    <UserControl.DataContext>
        <local:Dummy/>
    </UserControl.DataContext>
    
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <H:BaseHeadline Title="funktioniert"/>
            <H:BaseHeadline Title="{Binding TestText}"/>
            <TextBlock Text="{Binding TestText}"/>
        </StackPanel>
    </Grid>
</UserControl>

Die dazugehörige CodeBehind-Datei enthält keinen weiteren Code. Es wurde aber eine Dummy-Klasse dem Projekt hinzugefügt, welche zu Testzwecken Daten fürs Binding enthält:


// using ...

namespace TEST_Libs_Testing_Components
{
    public class Dummy : INotifyPropertyChanged
    {
        private String _TestText;
        public String TestText
        {
            get
            {
                return this._TestText;
            }
            private set
            {
                if (this._TestText != value)
                {
                    this._TestText = value;
                    OnPropertyChanged("TestText");
                }
            }
        }

        public Dummy()
        {
            this.TestText = "Hello World";
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}


Das Ergebnis ist, dass das Binding für mein CustomControl nicht funktioniert. Der TextBlock zeigt "Hello World", mein CustomControl bleibt leer. Wenn ich das Title-Attribut aber direkt mit einem Wert versehe und nicht das Binding nutze, wird mir der Text korrekt dargestellt....

Was fehlt meiner Klasse BaseHeadline, damit auch hier der Text entsprechend dargestellt wird?



Vielen Dank für Eure Hilfe!!!
private Nachricht | Beiträge des Benutzers
CSharperUser
myCSharp.de - Member



Dabei seit:
Beiträge: 81

beantworten | zitieren | melden

Hallo N0ACE,

nimm am Besten das Binding für den DataContext in deinem UserControl aus dem XAML und definiere es im Codebehind des Controls:


// using ...

namespace TEST_Headlines
{
    public partial class BaseHeadline : UserControl
    {
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
            "Title",
            typeof(string),
            typeof(BaseHeadline),
            null
        );

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public BaseHeadline()
        {
            InitializeComponent();
            DataContext = this;
        }
    }
}

Alternativ kannst du auch z.B. beim Binding auf Title noch die Quelle (also das Control selbst) über ElementName oder RelativeSource-Binding angeben.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von CSharperUser am .
private Nachricht | Beiträge des Benutzers
N0ACE
myCSharp.de - Member



Dabei seit:
Beiträge: 5

Themenstarter:

beantworten | zitieren | melden

Hi und danke für den Tipp!

Wenn ich den DataContext in der CodeBehind-Datei definiere, funktioniert dies leider noch immer nicht; das Verhalten ist vorher.
Aber mir ist da noch was anderes aufgefallen: Wenn ich in meinem CustomControll das Binding der Text-Property des TextBlocks nicht näher definiere (also keinen Path angebe), so wird in meinem TestProjekt gebunden; zwar wird nur Klassenpfad dargestellt (weil er ja nicht weiß, welches Element er binden soll), aber er bindet sowohl bei der direkten Zuweisung (<H:BaseHeadline Title="Test"/>) als auch beim Binding (<H:BaseHeadline Title={Binding TestText}/>)

Des Weiteren habe ich noch folgendes versucht: Das CustomControl hat einen Namen bekommen (x:Name="Base"):

<UserControl x:Class="TEST_Headlines.BaseHeadline"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:TEST_Headlines"
             mc:Ignorable="d"
             d:DesignHeight="50" d:DesignWidth="400"
             x:Name="Base"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    
    <Grid>
        <Border/>
        <TextBlock Text="{Binding Path=Title, ElementName=Base}"/>
    </Grid>
</UserControl>

Hier ist jetzt das Interessante, das in meinem Testprojekt zwar beides Mal mein CustomControl dargestellt wird, aber beim Setzen des Titles via Binding (<H:BaseHeadline Title={Binding TestText}/>) wird kein Text dargestellt (aber ein "leeres" Element; es collapsed nicht).


Für weitere Hilfe wäre ich sehr dankbar!
private Nachricht | Beiträge des Benutzers
lutzeslife
myCSharp.de - Member



Dabei seit:
Beiträge: 157
Herkunft: Dresden

beantworten | zitieren | melden

Versuche folgendes in deinem UserControl. Entferne den x:Name und DataContext Angabe. Dann gib dem Ersten Element deines UserControl (Grid) mit x:Name einen Namen z.B. Root. Im Konstructor legst du Fest Root.DataContext=this. Damit legst du den DatenContext des Grid auf das UserControl selber. Das DataBinding deines Textblocks musst du ändern. Nimm dort noch den ElementName weg. Die Path Angabe reicht.
Dann sollte es gehen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von lutzeslife am .
Mit freundlichen Grüßen
lutzeslife
private Nachricht | Beiträge des Benutzers