wpf c#通过DependencyProperty绑定两个视图模型不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wpf c#通过DependencyProperty绑定两个视图模型不起作用相关的知识,希望对你有一定的参考价值。

我想在主细节关系中使用两个视图模型创建一个View。 (客户订单)

我想将一个主视图模型的SelectedCustomer绑定到详细视图模型的SelectedCustomer。我读到实现DependencyProperty可以完成这项工作,但是我没有更新属性,因为我在父视图中选择了不同的客户。我有什么想法吗?

谢谢

ViewModels的代码是:

namespace BindingViewModels.ViewModels
{
    public class vmCustomers : INotifyPropertyChanged 
    {
        protected ObservableCollection<Customer> _customers;
        protected Customer _SelectedCustomer = null;
        public event PropertyChangedEventHandler PropertyChanged;

        public vmCustomers()
        {
            _customers = new ObservableCollection<Customer>();

            _customers.Add( new Customer() { CustomerID = 1, CustName = "John Doe" });
            _customers.Add(new Customer() { CustomerID = 2, CustName = "Johny Walker" });
            _customers.Add(new Customer() { CustomerID = 3, CustName = "Joe Foreman" });
            _customers.Add(new Customer() { CustomerID = 4, CustName = "Mike Tyson" });
            _customers.Add(new Customer() { CustomerID = 5, CustName = "Salvatore Ferragamo" });
            _customers.Add(new Customer() { CustomerID = 6, CustName = "Pato Donald" });
        }

        public ObservableCollection<Customer> Customers
        {
            get { return _customers; }
            set { _customers = value; }
        }

        public Customer SelectedCustomer
        {
            get
            {
                return _SelectedCustomer;
            }

            set
            {
                _SelectedCustomer = value;
                OnPropertyChanged("SelectedCustomer");
            }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(name));
        }
    }

    public class vmOrders : DependencyObject
    {
        public static readonly DependencyProperty SelectedCustomerProperty = 
            DependencyProperty.Register("SelectedCustomer", 
                typeof(Customer), 
                typeof(vmOrders), 
                new PropertyMetadata(default(Customer), OnItemsPropertyChanged));

        private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        protected ObservableCollection<Order> _AllOrders;
        protected ObservableCollection<Order> _CustomerOrders = null;
        protected Customer _SelectedCustomer = null;

        public vmOrders()
        {
            _AllOrders = new ObservableCollection<Order>();

            _AllOrders.Add(new Order() { OrderID = 1, CustomerID = 1, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 100 });
            _AllOrders.Add(new Order() { OrderID = 2, CustomerID = 1, Date = System.DateTime.Parse("2017-01-02"), TotalAmount = 200 });
            _AllOrders.Add(new Order() { OrderID = 3, CustomerID = 1, Date = System.DateTime.Parse("2017-01-03"), TotalAmount = 300 });
            _AllOrders.Add(new Order() { OrderID = 4, CustomerID = 1, Date = System.DateTime.Parse("2017-01-04"), TotalAmount = 400 });
            _AllOrders.Add(new Order() { OrderID = 5, CustomerID = 2, Date = System.DateTime.Parse("2017-01-05"), TotalAmount = 500 });
            _AllOrders.Add(new Order() { OrderID = 6, CustomerID = 2, Date = System.DateTime.Parse("2017-01-06"), TotalAmount = 600 });
            _AllOrders.Add(new Order() { OrderID = 7, CustomerID = 3, Date = System.DateTime.Parse("2017-01-07"), TotalAmount = 700 });
            _AllOrders.Add(new Order() { OrderID = 8, CustomerID = 3, Date = System.DateTime.Parse("2017-01-08"), TotalAmount = 800 });
            _AllOrders.Add(new Order() { OrderID = 9, CustomerID = 3, Date = System.DateTime.Parse("2017-01-09"), TotalAmount = 900 });
            _AllOrders.Add(new Order() { OrderID = 10, CustomerID = 3, Date = System.DateTime.Parse("2017-01-10"), TotalAmount = 1000 });
            _AllOrders.Add(new Order() { OrderID = 11, CustomerID = 3, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1200 });
            _AllOrders.Add(new Order() { OrderID = 12, CustomerID = 3, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1400 });
            _AllOrders.Add(new Order() { OrderID = 13, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1200 });
            _AllOrders.Add(new Order() { OrderID = 14, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5450 });
            _AllOrders.Add(new Order() { OrderID = 15, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5020 });
            _AllOrders.Add(new Order() { OrderID = 16, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5020 });
            _AllOrders.Add(new Order() { OrderID = 17, CustomerID = 5, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5030 });
            _AllOrders.Add(new Order() { OrderID = 18, CustomerID = 5, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5050 });
        }

        public ObservableCollection<Order> Orders
        {
            get {
                if (SelectedCustomer != null)
                    return _CustomerOrders;
                else
                    return _AllOrders;
            }
            set {
                _AllOrders = value;
                if (SelectedCustomer != null)
                {
                    var linqresults = _AllOrders.Where(o => o.CustomerID == _SelectedCustomer.CustomerID);
                    _CustomerOrders = new ObservableCollection<Order>(linqresults);
                }
                else
                {
                    _CustomerOrders = null;
                }
            }
        }

        public Customer SelectedCustomer
        {
            get
            {
                return (Customer)GetValue(SelectedCustomerProperty);
            }

            set
            {
                SetValue(SelectedCustomerProperty, value);
                _SelectedCustomer = SelectedCustomer;
            }
        }
    }

该视图的XAML是:

<Window x:Class="BindingViewModels.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindingViewModels"
        xmlns:ViewModels="clr-namespace:BindingViewModels.ViewModels"
        xmlns:Views="clr-namespace:BindingViewModels.Views"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type ViewModels:vmCustomers}">
            <Views:ViewCustomers/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ViewModels:vmOrders}">
            <Views:ViewOrders/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="200"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ContentPresenter Grid.Row="0" Name="ContentCustomers"  Content="{Binding ElementName=vmCustomersInstance}">
            <ContentPresenter.DataContext>
                <ViewModels:vmCustomers x:Name="vmCustomersInstance"/>
            </ContentPresenter.DataContext>
        </ContentPresenter>
        <ContentPresenter Grid.Row="1" Name="ContentOrders"  Content="{Binding ElementName= vmOrdersInstance}" MouseEnter="ContentOrders_MouseEnter">
            <ContentPresenter.DataContext>
                <ViewModels:vmOrders x:Name="vmOrdersInstance" SelectedCustomer="{Binding ElementName=vmCustomersInstance, Path=SelectedCustomer, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
            </ContentPresenter.DataContext>
        </ContentPresenter>
    </Grid>
</Window>

两个视图都是具有Grid和DataGrid的用户控件。

<UserControl x:Class="BindingViewModels.Views.ViewCustomers"
....
<Grid>
    <DataGrid Name="DataGrid" ItemsSource="{Binding Path=Customers}" SelectedItem="{Binding Path=SelectedCustomer}" AutoGenerateColumns="True" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
</Grid>

<UserControl x:Class="BindingViewModels.Views.ViewOrders"
....
<Grid>
    <DataGrid Name="DataGrid" ItemsSource="{Binding Path=Orders}" AutoGenerateColumns="True" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
</Grid>
答案

经过多次尝试,我终于开始工作了。

综合观点:

<Window x:Class="BindingVM2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindingVM2"
        xmlns:ViewModels="clr-namespace:BindingVM2.ViewModels"
        xmlns:Views="clr-namespace:BindingVM2.Views"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type ViewModels:vmCustomers}">
            <Views:ViewCustomers/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type ViewModels:vmOrders}">
            <Views:ViewOrders/>
        </DataTemplate>
        <ViewModels:vmCustomers x:Key="vmCustomerInstance" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="200"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ContentPresenter Grid.Row="0" Name="ContentCustomers"  Content="{StaticResource vmCustomerInstance}"/>
        <ContentPresenter Grid.Row="1" Name="ContentOrders"  Content="{Binding ElementName=vmOrdersInstance}">
            <ContentPresenter.DataContext>
                <ViewModels:vmOrders x:Name="vmOrdersInstance"  SelectedCustomer="{Binding Source={StaticResource vmCustomerInstance}, Path=SelectedCustomer , Mode=TwoWay}" />
            </ContentPresenter.DataContext>
        </ContentPresenter>
    </Grid>
</Window>

和ViewModels:

    public class vmCustomers : DependencyObject, INotifyPropertyChanged 
    {
        protected ObservableCollection<Customer> _customers;
        public event PropertyChangedEventHandler PropertyChanged;

        public static DependencyProperty SelectedCustomerProperty =
            DependencyProperty.Register( "SelectedCustomer", typeof(Customer), typeof(vmCustomers),
                        new PropertyMetadata(default(Customer), new PropertyChangedCallback(OnSelectedCustomerChanged)));

        private static void OnSelectedCustomerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Customer value = (Customer)e.NewValue;
            vmCustomers vm = (vmCustomers)d;

            vm.OnPropertyChanged("SelectedCustomer");
        }

        public Customer SelectedCustomer
        {
            get { return (Customer)GetValue(SelectedCustomerProperty); }
            set { SetValue(SelectedCustomerProperty, value); }
        }


        public vmCustomers()
        {
            _customers = new ObservableCollection<Customer>();

            _customers.Add( new Customer() { CustomerID = 1, CustName = "John Doe" });
            _customers.Add(new Customer() { CustomerID = 2, CustName = "Johny Walker" });
            _customers.Add(new Customer() { CustomerID = 3, CustName = "Joe Foreman" });
            _customers.Add(new Customer() { CustomerID = 4, CustName = "Mike Tyson" });
            _customers.Add(new Customer() { CustomerID = 5, CustName = "Salvatore Ferragamo" });
            _customers.Add(new Customer() { CustomerID = 6, CustName = "Pato Donald" });
        }

        public ObservableCollection<Customer> Customers
        {
            get { return _customers; }
            set { _customers = value; }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(name));
        }
    }

    public class vmOrders : DependencyObject ,INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected ObservableCollection<Order> _AllOrders;
        protected ObservableCollection<Order> _CustomerOrders = null;

        public static DependencyProperty SelectedCustomerProperty =
                    DependencyProperty.Register( "SelectedCustomer", typeof(Customer), typeof(vmOrders),
                        new FrameworkPropertyMetadata(default(Customer), new PropertyChangedCallback(OnSelectedCustomerPropertyChanged)));

        private static void OnSelectedCustomerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Customer value = (Customer)e.NewValue;
            vmOrders vm = (vmOrders)d;

            vm.ApplyFilter();
            vm.OnPropertyChanged("Orders");
        }

        public Customer SelectedCustomer
        {
            get {return (Customer)GetValue(SelectedCustomerProperty); }
            set { SetValue(SelectedCustomerProperty, value); }
        }

        public vmOrders()
        {
            _AllOrders = new ObservableCollection<Order>();

            _AllOrders.Add(new Order() { OrderID = 1, CustomerID = 1, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 100 });
            _AllOrders.Add(new Order() { OrderID = 2, CustomerID = 1, Date = System.DateTime.Parse("2017-01-02"), TotalAmount = 200 });
            _AllOrders.Add(new Order() { OrderID = 3, CustomerID = 1, Date = System.DateTime.Parse("2017-01-03"), TotalAmount = 300 });
            _AllOrders.Add(new Order() { OrderID = 4, CustomerID = 1, Date = System.DateTime.Parse("2017-01-04"), TotalAmount = 400 });
            _AllOrders.Add(new Order() { OrderID = 5, CustomerID = 2, Date = System.DateTime.Parse("2017-01-05"), TotalAmount = 500 });
            _AllOrders.Add(new Order() { OrderID = 6, CustomerID = 2, Date = System.DateTime.Parse("2017-01-06"), TotalAmount = 600 });
            _AllOrders.Add(new Order() { OrderID = 7, CustomerID = 3, Date = System.DateTime.Parse("2017-01-07"), TotalAmount = 700 });
            _AllOrders.Add(new Order() { OrderID = 8, CustomerID = 3, Date = System.DateTime.Parse("2017-01-08"), TotalAmount = 800 });
            _AllOrders.Add(new Order() { OrderID = 9, CustomerID = 3, Date = System.DateTime.Parse("2017-01-09"), TotalAmount = 900 });
            _AllOrders.Add(new Order() { OrderID = 10, CustomerID = 3, Date = System.DateTime.Parse("2017-01-10"), TotalAmount = 1000 });
            _AllOrders.Add(new Order() { OrderID = 11, CustomerID = 3, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1200 });
            _AllOrders.Add(new Order() { OrderID = 12, CustomerID = 3, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1400 });
            _AllOrders.Add(new Order() { OrderID = 13, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 1200 });
            _AllOrders.Add(new Order() { OrderID = 14, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5450 });
            _AllOrders.Add(new Order() { OrderID = 15, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5020 });
            _AllOrders.Add(new Order() { OrderID = 16, CustomerID = 4, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5020 });
            _AllOrders.Add(new Order() { OrderID = 17, CustomerID = 5, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5030 });
            _AllOrders.Add(new Order() { OrderID = 18, CustomerID = 5, Date = System.DateTime.Parse("2017-01-01"), TotalAmount = 5050 });
        }

        public void ApplyFilter()
        {
            if (SelectedCustomer != null)
            {
                var linqresults = _AllOrders.Where(o => o.CustomerID == SelectedCustomer.CustomerID);
                _CustomerOrders = new ObservableCollection<Order>(linqresults);
            }
            else
            {
                _CustomerOrders = null;
            }
        }
        public Obser

以上是关于wpf c#通过DependencyProperty绑定两个视图模型不起作用的主要内容,如果未能解决你的问题,请参考以下文章

C#/WPF:禁用 RichTextBox 的文本换行

现在都有wpf了,c++做应用还有啥优势

匿名管道 c# WPF

WPF中RichTextBox的定位问题。如何使光标定位到与指定关键字所在的位置?

将现有 RESX 文件导入 C#/WPF 项目的正确过程

WPF C#实现了一个调整大小的抓握