在嵌套的用户控件之间绑定数据
Binding Data Between Nested UserControls
我有一个 mainwindow,我生成它来启动驱动一系列用户控件的应用程序。默认情况下,main window 里面有一个用户控件。我在将依赖对象从子用户控件传播到父用户控件时遇到了挑战。预先警告,我是一名 DBA,这是我第一次接触 MVVM,因此该方法可能完全无效。如果您需要任何其他代码片段,我也可以提供它们:)。这个window里面有一个用户控件:
<Grid>
<views:UserControl1 Name="ViewOne" DeviceName="DEVICE1" EventNumber="EVENT1" />
</Grid>
该用户控件包含两个依赖对象:一个接收设备和另一个接收事件的设备。根据我发送的项目(或者如果两者都设置则订购),我更改 UserControl1 中任何后续用户控件的数据源。这是 UserControl1 中的两个依赖对象:
public partial class UserControl1: UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string DeviceName
{
get { return (string)GetValue(DeviceNameProperty); }
set { SetValue(DeviceNameProperty, value); }
}
public static readonly DependencyProperty DeviceNameProperty =
DependencyProperty.Register("DeviceName", typeof(string), typeof(UserControl1), new PropertyMetadata(String.Empty));
public string EventNumber
{
get { return (string)GetValue(EventNumberProperty); }
set { SetValue(EventNumberProperty, value); }
}
public static readonly DependencyProperty EventNumberProperty =
DependencyProperty.Register("EventNumber", typeof(string), typeof(UserControl1), new PropertyMetadata(String.Empty));
}
在 Usercontrol1 中,我有两个额外的用户控件,它们接受来自 usercontrol1 的设备号和事件号,由 mainwindow 传递或设置。
<UserControl x:Class="Omitted"
Background="White" Name="FLP" >
<Grid Name="rootDataGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<GroupBox Header="Summary" Grid.Row="0" Grid.Column="0">
<fv:VerticalSummary x:Name="VFS" DeviceName="{Binding Path=DeviceName, ElementName=FLP, Mode=TwoWay}" EventNumber="{Binding Path=EventNumber, ElementName=FLP}" />
</GroupBox>
<GroupBox Header="Tags" Grid.Row="0" Grid.Column="1">
<tags:Tags x:Name="TBF" DeviceName="{Binding Path=DeviceName, ElementName=FLP, Mode=TwoWay}" EventNumber="{Binding Path=EventNumber, ElementName=FLP}" />
</GroupBox>
一切正常,将数据从 window 发送到父控件,然后从父控件向下发送到两个用户控件。不幸的是,如果我更改我的一个用户控件(垂直摘要)中的值,它不会冒泡到顶部控件,然后向下渗透到其他控件。这是垂直摘要视图(代码隐藏)以供参考:
VerticalSummaryViewModel _vm;
public VerticalSummary()
{
InitializeComponent();
_vm = (VerticalSummaryViewModel)rootGrid.DataContext;
}
public string DeviceName
{
get { return (string)GetValue(DeviceNameProperty); }
set { SetValue(DeviceNameProperty, value); }
}
public static readonly DependencyProperty DeviceNameProperty =
DependencyProperty.Register("DeviceName", typeof(string), typeof(VerticalSummary), new PropertyMetadata(String.Empty, OnDeviceNameSet));
public static void OnDeviceNameSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((VerticalSummary)d)._vm.DeviceName = e.NewValue.ToString();
}
public string EventNumber
{
get { return (string)GetValue(EventNumberProperty); }
set { SetValue(EventNumberProperty, value); }
}
public static readonly DependencyProperty EventNumberProperty =
DependencyProperty.Register("EventNumber", typeof(string), typeof(VerticalSummary), new PropertyMetadata(String.Empty, OnEventNumberSet));
public static void OnEventNumberSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((VerticalSummary)d)._vm.EventNumber = e.NewValue.ToString();
}
这里是供参考的VerticalSummaryViewModel:
public class VerticalSummaryViewModel : ObservableObject
{
private OMSRepository _repo;
private ObservableCollection<OMS> _feeders;
public ObservableCollection<OMS> Feeders
{
get { return _feeders; }
set {
if (value != _feeders)
{
_feeders = value;
OnPropertyChanged("Feeders");
}
}
}
private OMS _selectedFeeder;
public OMS SelectedFeeder
{
get { return _selectedFeeder; }
set
{
if(_selectedFeeder != value)
{
_selectedFeeder = value;
DeviceName = _selectedFeeder.OMSName;
OnPropertyChanged("SelectedFeeder");
}
}
}
private string _eventNumber;
public string EventNumber
{
get { return _eventNumber; }
set
{
if (value != _eventNumber)
{
_eventNumber = value;
OnPropertyChanged("EventNumber");
}
}
}
private string _deviceName;
public string DeviceName
{
get { return _deviceName; }
set
{
if (value != _deviceName)
{
_deviceName = value;
OnPropertyChanged("DeviceName");
}
}
}
public VerticalSummaryViewModel()
{
_repo = new OMSRepository();
LoadFeederDropDown();
LoadFeederSummary();
}
private void LoadFeederSummary()
{
}
private void LoadFeederDropDown()
{
Feeders = _repo.GetFeeders();
}
}
我建议您根据自己的情况考虑使用 MVVM(这在 WPF 中很常见)。
您最终要做的是创建一个包含您的业务数据的 ViewModel (VM)(将其视为临时数据 table)。然后,您将需要将控件特定数据直接绑定到 VM 上的属性。
通过在两个绑定上指定 mode=TwoWay
,当一个控件更改共享绑定时,另一个绑定将收到数据已更改的通知并在其控件中显示更改。
我写了一篇关于 MVVM 的文章作为一个很好的起点Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding
我有一个 mainwindow,我生成它来启动驱动一系列用户控件的应用程序。默认情况下,main window 里面有一个用户控件。我在将依赖对象从子用户控件传播到父用户控件时遇到了挑战。预先警告,我是一名 DBA,这是我第一次接触 MVVM,因此该方法可能完全无效。如果您需要任何其他代码片段,我也可以提供它们:)。这个window里面有一个用户控件:
<Grid>
<views:UserControl1 Name="ViewOne" DeviceName="DEVICE1" EventNumber="EVENT1" />
</Grid>
该用户控件包含两个依赖对象:一个接收设备和另一个接收事件的设备。根据我发送的项目(或者如果两者都设置则订购),我更改 UserControl1 中任何后续用户控件的数据源。这是 UserControl1 中的两个依赖对象:
public partial class UserControl1: UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string DeviceName
{
get { return (string)GetValue(DeviceNameProperty); }
set { SetValue(DeviceNameProperty, value); }
}
public static readonly DependencyProperty DeviceNameProperty =
DependencyProperty.Register("DeviceName", typeof(string), typeof(UserControl1), new PropertyMetadata(String.Empty));
public string EventNumber
{
get { return (string)GetValue(EventNumberProperty); }
set { SetValue(EventNumberProperty, value); }
}
public static readonly DependencyProperty EventNumberProperty =
DependencyProperty.Register("EventNumber", typeof(string), typeof(UserControl1), new PropertyMetadata(String.Empty));
}
在 Usercontrol1 中,我有两个额外的用户控件,它们接受来自 usercontrol1 的设备号和事件号,由 mainwindow 传递或设置。
<UserControl x:Class="Omitted"
Background="White" Name="FLP" >
<Grid Name="rootDataGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<GroupBox Header="Summary" Grid.Row="0" Grid.Column="0">
<fv:VerticalSummary x:Name="VFS" DeviceName="{Binding Path=DeviceName, ElementName=FLP, Mode=TwoWay}" EventNumber="{Binding Path=EventNumber, ElementName=FLP}" />
</GroupBox>
<GroupBox Header="Tags" Grid.Row="0" Grid.Column="1">
<tags:Tags x:Name="TBF" DeviceName="{Binding Path=DeviceName, ElementName=FLP, Mode=TwoWay}" EventNumber="{Binding Path=EventNumber, ElementName=FLP}" />
</GroupBox>
一切正常,将数据从 window 发送到父控件,然后从父控件向下发送到两个用户控件。不幸的是,如果我更改我的一个用户控件(垂直摘要)中的值,它不会冒泡到顶部控件,然后向下渗透到其他控件。这是垂直摘要视图(代码隐藏)以供参考:
VerticalSummaryViewModel _vm;
public VerticalSummary()
{
InitializeComponent();
_vm = (VerticalSummaryViewModel)rootGrid.DataContext;
}
public string DeviceName
{
get { return (string)GetValue(DeviceNameProperty); }
set { SetValue(DeviceNameProperty, value); }
}
public static readonly DependencyProperty DeviceNameProperty =
DependencyProperty.Register("DeviceName", typeof(string), typeof(VerticalSummary), new PropertyMetadata(String.Empty, OnDeviceNameSet));
public static void OnDeviceNameSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((VerticalSummary)d)._vm.DeviceName = e.NewValue.ToString();
}
public string EventNumber
{
get { return (string)GetValue(EventNumberProperty); }
set { SetValue(EventNumberProperty, value); }
}
public static readonly DependencyProperty EventNumberProperty =
DependencyProperty.Register("EventNumber", typeof(string), typeof(VerticalSummary), new PropertyMetadata(String.Empty, OnEventNumberSet));
public static void OnEventNumberSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((VerticalSummary)d)._vm.EventNumber = e.NewValue.ToString();
}
这里是供参考的VerticalSummaryViewModel:
public class VerticalSummaryViewModel : ObservableObject
{
private OMSRepository _repo;
private ObservableCollection<OMS> _feeders;
public ObservableCollection<OMS> Feeders
{
get { return _feeders; }
set {
if (value != _feeders)
{
_feeders = value;
OnPropertyChanged("Feeders");
}
}
}
private OMS _selectedFeeder;
public OMS SelectedFeeder
{
get { return _selectedFeeder; }
set
{
if(_selectedFeeder != value)
{
_selectedFeeder = value;
DeviceName = _selectedFeeder.OMSName;
OnPropertyChanged("SelectedFeeder");
}
}
}
private string _eventNumber;
public string EventNumber
{
get { return _eventNumber; }
set
{
if (value != _eventNumber)
{
_eventNumber = value;
OnPropertyChanged("EventNumber");
}
}
}
private string _deviceName;
public string DeviceName
{
get { return _deviceName; }
set
{
if (value != _deviceName)
{
_deviceName = value;
OnPropertyChanged("DeviceName");
}
}
}
public VerticalSummaryViewModel()
{
_repo = new OMSRepository();
LoadFeederDropDown();
LoadFeederSummary();
}
private void LoadFeederSummary()
{
}
private void LoadFeederDropDown()
{
Feeders = _repo.GetFeeders();
}
}
我建议您根据自己的情况考虑使用 MVVM(这在 WPF 中很常见)。
您最终要做的是创建一个包含您的业务数据的 ViewModel (VM)(将其视为临时数据 table)。然后,您将需要将控件特定数据直接绑定到 VM 上的属性。
通过在两个绑定上指定 mode=TwoWay
,当一个控件更改共享绑定时,另一个绑定将收到数据已更改的通知并在其控件中显示更改。
我写了一篇关于 MVVM 的文章作为一个很好的起点Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding