【问题标题】:How to pass data from MainWindow to a User Control that's inside the MainWindow?如何将数据从 MainWindow 传递到 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 并在那里执行所有与用户控制相关的操作。看这是编程,你可以使用任何流程和结构来完成任何任务,但是一旦你的应用程序增长,你可能会发现很难管理代码更改。

标签: c# wpf xaml


【解决方案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 对象。

【讨论】:

    猜你喜欢
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多