如何将数据从 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<Order> 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 内的用户控件?的主要内容,如果未能解决你的问题,请参考以下文章
Qt:通过类 C 将变量从 ClassA 传递到 ClassB