Laden...

Frage: Einfaches CustomControl mit Binding via DependencyProperty

Erstellt von N0ACE vor 9 Jahren Letzter Beitrag vor 9 Jahren 5.873 Views
N
N0ACE Themenstarter:in
5 Beiträge seit 2014
vor 9 Jahren
Frage: Einfaches CustomControl mit Binding via DependencyProperty

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!!!

C
80 Beiträge seit 2010
vor 9 Jahren

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.

N
N0ACE Themenstarter:in
5 Beiträge seit 2014
vor 9 Jahren

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!

L
155 Beiträge seit 2012
vor 9 Jahren

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.

Mit freundlichen Grüßen
lutzeslife