web-dev-qa-db-fra.com

Liaison de données dans les contrôles utilisateur WPF

Je crée un UserControl pour une série de contrôles partagés par plusieurs fenêtres. L'un des contrôles est une étiquette qui montre le flux d'un autre processus en termes de "numéros de protocole".

J'essaie d'offrir DataBinding avec cette étiquette afin que la fenêtre reflète automatiquement l'état du processus lorsque la variable de numéro de protocole change.

Voici le contrôle utilisateur XAML:

<UserControl Name="MainOptionsPanel"
    x:Class="ExperienceMainControls.MainControls"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
<Label Height="Auto" Name="numberLabel">Protocol:</Label>
<Label Content="{Binding Path=ProtocolNumber}" Name="protocolNumberLabel"/>
(...)
</UserControl>

Et voici le code-derrière:

public partial class MainControls 
{
    public MainControls()
    {
        InitializeComponent();
    }

    public int ProtocolNumber
    {
        get { return (int)GetValue(ProtocolNumberProperty); }
        set { SetValue(ProtocolNumberProperty, value); }
    }

    public static DependencyProperty ProtocolNumberProperty = 
       DependencyProperty.Register("ProtocolNumber", typeof(int), typeof(MainControls));
}

Cela semble fonctionner parce que si sur le constructeur j'ai défini ProtocolNumber sur une valeur arbitraire, cela se reflète dans le contrôle utilisateur.

Toutefois, lorsque vous utilisez ce contrôle utilisateur sur la fenêtre finale, la liaison de données est interrompue.

XAML:

<Window x:Class="UserControlTesting.Window1"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml" xmlns:expControl="clr-namespace:ExperienceMainControls;Assembly=ExperienceMainControls"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
    <StackPanel>
        <expControl:MainControls ProtocolNumber="{Binding Path=Number, Mode=TwoWay}" />
    </StackPanel>

</Window>

Code-Derrière pour la fenêtre:

public partial class Window1 : Window
{
    public Window1()
    {
        Number= 15;
        InitializeComponent();
    }

    public int Number { get; set; }
}

Cela définit le numéro de protocole à zéro, ignorant la valeur définie sur nombre.

J'ai lu l'exemple

31
Gabriel Sanmartin

si vous regardez votre fenêtre de sortie, vous devriez voir l'exception de liaison.

Le problème que vous rencontrez est le suivant: dans votre contrôle utilisateur, vous lierez l'étiquette au DP ProtocolNumber de votre contrôle utilisateur et non au DataContext, vous devez donc ajouter par exemple le nom de l'élément à la liaison.

<UserControl Name="MainOptionsPanel"
    x:Class="ExperienceMainControls.MainControls"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    x:Name="uc"
    >
<Label Height="Auto" Name="numberLabel">Protocol:</Label>
<Label Content="{Binding Path=ProtocolNumber, ElementName=uc}" Name="protocolNumberLabel"/>
(...)
</UserControl>

EDIT: pour effacer certaines choses, votre contrôle utilisateur fonctionne également si vous modifiez la liaison dans votre fenêtre principale. mais vous devez vous lier au DataContext de MainWindow avec RelativeSource.

    <expControl:MainControls ProtocolNumber="{Binding Path=Number, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
39
blindmeis

Ce que vous avez en effet:

<expControl:MainControls DataContext="{Binding RelativeSource={RelativeSource Self}}"
                         ProtocolNumber="{Binding Path=Number, Mode=TwoWay}"/>

=> Do not définissez les déclarations DataContext dans UserControl, utilisez plutôt les liaisons RelativeSource ou ElementName.

6
H.B.

Si vous ne spécifiez pas le RelativeSource de la liaison, essayez de définir le DataContext dans le constructeur:

    public Window1()
    {
        Number= 15;
        DataContext = this;
        InitializeComponent();
    }
2
Mizipzor