在嵌套的UserControl之间绑定数据

时间:2017-10-17 20:23:14

标签: c# wpf xaml user-controls dependencyobject

我有一个主窗口,我生成它来启动我的应用程序,驱动一系列用户控件。默认情况下,主窗口中有一个usercontrol。我在将子用户控件中的dependencyobjects传播回父用户控件方面遇到了挑战。预警,我是一名DBA,这是我对MVVM的第一次尝试,因此这种方法可能完全无效。如果您需要任何其他代码片段,我也可以提供它们:)。这个窗口里面有一个用户控件:

<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的设备和事件编号,该编号由主窗口传递或设置。

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

一切正常,可以将数据从窗口发送到父控件,然后将父控件发送到两个用户控件。不幸的是,如果我更改了我的一个用户控件(垂直摘要)中的值,它不会冒泡到顶部控件,然后逐渐下降到其他控件。以下是垂直摘要视图(代码隐藏)供参考:

 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();
    }       
}

1 个答案:

答案 0 :(得分:0)

我建议你考虑在你的情况下使用MVVM(这是WPF中常见的)。

您最终要做的是创建一个包含业务数据的ViewModel(VM)(将其视为临时表)。然后,您将控件特定数据需求直接绑定到VM上的属性。

通过在两个绑定上指定mode=TwoWay,当一个控件更改共享绑定时,绑定其他绑定将收到数据已更改的通知并显示其控件中的更改。

我已经写了一篇关于MVVM的文章,以获得一个好的启动点Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding