如何将数据从 MainWindow 传递到 MainWindow 内的用户控件?

Posted

技术标签:

【中文标题】如何将数据从 MainWindow 传递到 MainWindow 内的用户控件?【英文标题】:How to pass data from MainWindow to a User Control that's inside the MainWindow? 【发布时间】:2019-04-27 16:30:29 【问题描述】:

我进行了研究,发现人们倾向于使用 ViewModel 来实现这一点,但我有点陷入困境。

我有一个

public ObservableCollection<Order> orderList get; set; = new ObservableCollection<Order>();

MainWindow 中已经填满了数据。

在 MainWindow XAML 中,我在 TabControl 中有一个用户控件:

<TabControl x:Name="TabCollection">
        <TabItem Header="UC1">
            <local:UserControl1/>
        </TabItem>
        <TabItem Header="UC2">
            <local:UserControl2/>
        </TabItem>
    </TabControl>

我们在这里只讨论 UC1,所以在 UC1 XAML 中我有一个 ListView 里面:

    <UserControl.DataContext>
    <local:UserControl1VM/>
</UserControl.DataContext>

<ListView x:Name="ListViewText">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="First name" DisplayMemberBinding="Binding Firstname"/>
            <GridViewColumn Header="Last Name" DisplayMemberBinding="Binding Lastname"/>
            <GridViewColumn Header="Order" DisplayMemberBinding="Binding Ordername"/>
            <GridViewColumn Header="Delivery time" DisplayMemberBinding="Binding Deliverytime"/>
            <GridViewColumn Header="Phone Number" DisplayMemberBinding="Binding Phone"/>
            <GridViewColumn Header="Address" DisplayMemberBinding="Binding Address"/>
            <GridViewColumn Header="Email" DisplayMemberBinding="Binding Email"/>
        </GridView>
    </ListView.View>
</ListView>

这是 UserControl1VM.cs 中的代码:

namespace QuickShop

class UserControl1VM : INotifyPropertyChanged

    private ObservableCollection<Order> orderList;
    public ObservableCollection<Order> OrderList
    
        get  return orderList; 
        set
        
            orderList = value;
            PropertyChanged(this, new PropertyChangedEventArgs("OrderList"));
        
    

    //
    private void FindDeliveryOrders(IEnumerable<Order> sortList)
    
        foreach (var order in sortList)
        
            if (order.Delivery.Equals("Yes"))
            
                //deliveryOrders.Add(order);
                this.ListViewText.Items.Add(new Order  Firstname = order.Firstname, Lastname = order.Lastname, Ordername = order.Ordername, Deliverytime = order.Deliverytime, Phone = order.Phone, Address = order.Address, Email = order.Email );
            
        
    

    public event PropertyChangedEventHandler PropertyChanged = delegate  ;


当然,这些都是不完整的代码,因为我不知道下一步该怎么做。

我的目标只是填充ListView,如果orderList 发生变化,它会自动更新。但是现在我什至不知道 ViewModel 是否正常工作,任何想法和代码演示都将非常感激。

【问题讨论】:

无需在MainWindow 中加入public ObservableCollection&lt;Order&gt; orderList。在UserControl1VM 中定义并实现它。 @GaurangDave 但这样做我必须将填充orderList 的整个方法移动到UserControl1VM 没错!我认为这将是 MVVM 的正确实现。您需要将相关的 VM 与其 View 分开。 @GaurangDave 那我为什么需要 ViewModel 我可以在自动生成的 UserControl1.xaml.cs 中实现它(因为该方法正在调用 SQL 数据库来读取数据并填充 orderList 所以它有点独立) Usercontrol 将显示一个列表,然后根据我的说法,最好的结构是您在 usercontrol 中连接 sql 并在那里执行所有与用户控制相关的操作。看这是编程,你可以使用任何流程和结构来完成任何任务,但是一旦你的应用程序增长,你可能会发现很难管理代码更改。 【参考方案1】:

用户控件不应该有“私有”视图模型,因为您将它分配给用户控件的 XAML 中的 DataContext。相反,它应该公开可以绑定到外部提供的视图模型对象的属性的依赖属性。

像这样声明ItemsSource 属性:

public partial class UserControl1 : UserControl

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register(
            nameof(ItemsSource), typeof(IEnumerable), typeof(UserControl1));

    public IEnumerable ItemsSource
    
        get  return (IEnumerable)GetValue(ItemsSourceProperty); 
        set  SetValue(ItemsSourceProperty, value); 
    

    public UserControl1()
    
        InitializeComponent();
    

并像这样绑定 ListView:

<UserControl ...>
    ...
    <ListView ItemsSource="Binding ItemsSource,
                            RelativeSource=RelativeSource AncestorType=UserControl">
        ...
    </ListView>
    ...
</UserControl>

当您使用 UserControl 时,将属性绑定到视图模型属性:

<TabItem Header="UC1">
    <local:UserControl1 ItemsSource="Binding OrderList"/>
</TabItem>

最后一个 XAML sn-p 假定 UserControl 的 DataContext 中的对象具有 OrderList 属性。当 TabControl 绑定到具有该属性的视图模型对象集合时,这将自动发生。


或者,让 UserControl 的 XAML 中的元素直接绑定到继承的 DataContext 中对象的属性。

<UserControl ...>
    ...
    <ListView ItemsSource="Binding OrderList">
        ...
    </ListView>
    ...
</UserControl>

您的控件不必公开额外的可绑定属性,但它只适用于实际提供预期源属性的 DataContext 对象。

【讨论】:

以上是关于如何将数据从 MainWindow 传递到 MainWindow 内的用户控件?的主要内容,如果未能解决你的问题,请参考以下文章

将变量从 MainWindow 传递到新窗口

WPF:将变量从父 xaml 传递到用户控件

Qt:通过类 C 将变量从 ClassA 传递到 ClassB

在python运行时将数据从GUI传递给线程

通过 Signal/Slot 机制将 QString 传递给 QThread

如何将值从主传递到对话框