Связывание данных в пользовательских элементах WPF
Я создаю UserControl для серии элементов управления, разделяемых несколькими окнами. Одним из элементов управления является метка, которая показывает поток какого-либо другого процесса с точки зрения "номеров протоколов".
Я пытаюсь предложить DataBinding с этой меткой, чтобы Окно автоматически отражало состояние процесса по мере изменения переменной номера протокола.
Это элемент управления пользователя 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>
И это Code-Behind:
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));
}
Кажется, что это работает, потому что если в конструкторе я устанавливаю ProtocolNumber на произвольное значение, он отображается в пользовательском элементе управления.
Однако при использовании этого usercontrol в конечном окне происходит срыв привязки данных.
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>
Код для окна:
public partial class Window1 : Window
{
public Window1()
{
Number= 15;
InitializeComponent();
}
public int Number { get; set; }
}
Это устанавливает номер протокола в ноль, игнорируя значение, установленное на Number.
Я читал пример
Ответы
Ответ 1
если вы посмотрите на окно вывода, вы должны увидеть исключение привязки.
У вас есть следующая проблема: в вашем пользовательском управлении вы привяжете метку к DP ProtocolNumber вашего usercontrol, а не к DataContext
, поэтому вам нужно добавить, например, имя элемента к привязке.
<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: чтобы очистить некоторые вещи, ваш usercontrol также работает, если вы измените привязку в своем MainWindow. но вы должны привязываться к DataContext MainWindow с RelativeSource.
<expControl:MainControls ProtocolNumber="{Binding Path=Number, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
Ответ 2
Что вы имеете в виду:
<expControl:MainControls DataContext="{Binding RelativeSource={RelativeSource Self}}"
ProtocolNumber="{Binding Path=Number, Mode=TwoWay}"/>
= > Сделайте не набор объявлений DataContext
в UserControl
, используйте привязки RelativeSource
или ElementName
.
Ответ 3
Если вы не указываете RelativeSource
привязки, попробуйте установить DataContext
в конструкторе:
public Window1()
{
Number= 15;
DataContext = this;
InitializeComponent();
}