具有MVVM数据绑定的WPF ComboBox [英] WPF ComboBox with MVVM Databinding

查看:55
本文介绍了具有MVVM数据绑定的WPF ComboBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

我遇到了一个组合框问题,但我似乎无法解决.让我先解释一下我目前的课程.我有两个用于将WPF用户控件绑定到的ViewModel类.

第一个是一个非常简单的类,仅公开了一些属性.此类称为EntityAddressViewModel 1)Linq to SQL地址对象-CurrentAddress(其中包含StatesOrProvince实体属性)
2)ICollectionView状态
3)Linq to SQL AddressType
4) boolean-InEditMode

第二个ViewModel类,称为CustomerShipToViewModel,稍微复杂一点,可以处理数据检索和在第一个ViewModel上设置属性的情况.除其他属性外,它还包含AddressViewModel的属性.现在,绑定到CustomerShipToViewModel类的User控件包含一个ContentPresenter控件,该控件已绑定到AddressViewModel属性.此用户控件中还定义了一个用于AddressViewModel数据类型的数据模板.

除组合框外,其他所有方法都可以正常工作.状态列表显示在列表中,但似乎未与CurrentAddress.StateProvice属性同步.

现在,对我来说似乎很古怪的是,如果我在其中放入CurrentAddress和States属性CustomerShipToViewModel只是包装了AddressViewModel属性,从而暴露了Address和ICollection属性,然后将新的组合框绑定到这两个属性,该行为在父"控件的组合框中以及在datatemplate中定义的组合框中均符合预期.

下面是代码.

公共类CustomerShipToViewModel:WorkspaceViewModel< ICustomerShipToView>
得到{return _currentAddress; }
设置{_currentAddress =值; OnPropertyChanged("AddressViewModel"); }
}

#endregion
}





公共类EntityAddressViewModel:DependencyObject
{{
public EntityAddressViewModel(){} {}
public address CurrentAddress
{
get {return(Address)GetValue(CurrentAddressProperty); }
设置{SetValue(CurrentAddressProperty,value); }
}

////使用DependencyProperty作为CurrentAddress的后备存储.这将启用动画,样式,绑定等...
公共静态只读DependencyProperty CurrentAddressProperty =
DependencyProperty.Register("CurrentAddress",typeof(Address),typeof(EntityAddressViewModel));

public ICollectionView States
{
的get {返回(ICollectionView)GetValue(StatesProperty); }
设置{SetValue(StatesProperty,value); }
}

////使用DependencyProperty作为州的后备存储.这将启用动画,样式,绑定等...
公共静态只读DependencyProperty StatesProperty =
DependencyProperty.Register(状态",typeof(ICollectionView),typeof(EntityAddressViewModel));

public ICollectionView AddressTypes
{
的get {返回(ICollectionView)GetValue(AddressTypesProperty); }
设置{SetValue(AddressTypesProperty,value); }
}

////使用DependencyProperty作为AddressTypes的后备存储.这将启用动画,样式,绑定等...
public static only DependencyProperty AddressTypesProperty =
DependencyProperty.Register("AddressTypes",typeof(ICollectionView),typeof(EntityAddressViewModel));


public bool InEditMode
{
get {return(bool)GetValue(InEditModeProperty); }
设置{SetValue(InEditModeProperty,value); }
}

////使用DependencyProperty作为InEditMode的后备存储.这将启用动画,样式,绑定等...
公共静态只读DependencyProperty InEditModeProperty =
DependencyProperty.Register("InEditMode",typeof(bool),typeof(EntityAddressViewModel),新的UIPropertyMetadata



public bool AddressTypeIsVisible
{{br> get {return(bool)GetValue(AddressTypeIsVisibleProperty); }
设置{SetValue(AddressTypeIsVisibleProperty,value); }
}

////使用DependencyProperty作为AddressTypeIsVisible的后备存储.这将启用动画,样式,绑定等.
}

//###############
//除了类型为EntityAddressViewModel的数据模板之外,< ComboBox Grid.Column =" 1"高度="25".保证金="4".名称="stateComboBox"; VerticalAlignment =顶部"
项ItemsSource ="{Binding Path = States,Mode = TwoWay}";的DisplayMemberPath = QUOT; StateProvinceCode"结果的SelectedValue = QUOT; {结合路径= CurrentAddress.StateProvince,模式=双向,UpdateSourceTrigger =的PropertyChanged}"结果,IsSynchronizedWithCurrentItem = QUOT;真" IsEnabled =``{Binding Path = InEditMode}''

根据其中包含的内容,我认为

CustomerShipToViewModel  提高 通过在属性设置器中调用OnPropertyChanged(...)方法, INotifyPropertyChanged.PropertyChanged 事件:

公共EntityAddressViewModel AddressViewModel
        {
            得到{return _currentAddress; }
            设置{_currentAddress =值; OnPropertyChanged("AddressViewModel"); }
        } 

The EntityAddressViewModel  ; class似乎未实现INotifyPropertyChanged,它 似乎在值更改时不会引发 INotifyPropertyChanged.PropertyChanged ,因此绑定控件不会更新.

我希望这会有所帮助. :)


Hello,

I'm experiencing a problem with a combo box that I just can't seem to solve.  Let me start by explaining my current classes.  I have two ViewModel classes that I use to bind WPF usercontrols to. 

The first is a very simple class which only exposes a few properties. This class is called EntityAddressViewModel
Properties
1) Linq to SQL Address object - CurrentAddress (Which contains a StatesOrProvince Entity Property)
2) ICollectionView States
3) Linq to SQL AddressType
4) boolean - InEditMode

The second ViewModel class, called CustomerShipToViewModel,  is a little more sophisticated and handles retreiving the data and setting the properties on the first ViewModel.  Among other properties it contains a property for AddressViewModel


Now the User control that is bound to the CustomerShipToViewModel class contains a ContentPresenter control which is bound to the AddressViewModel property.  Also defined in this user control is a datatemplate for data types of AddressViewModel.

Everything works great except for the combo box.  The list of states is shows in the list, but it does not appear to be syncronized with the CurrentAddress.StateProvice property.

Now what seems really wacky to me is that if I put a CurrentAddress and a States property in the CustomerShipToViewModel that simply wraps the AddressViewModel property exposing the Address and ICollection properties, and then bind a new combobox to those two properties, the behavior is as expected in both the combo box in the 'parent' control, and the combobox defined in the datatemplate.

Below is the code.

 public class CustomerShipToViewModel: WorkspaceViewModel<ICustomerShipToView>
    {
//Code excerpt
        public EntityAddressViewModel AddressViewModel
        {
            get { return _currentAddress; }
            set { _currentAddress = value; OnPropertyChanged("AddressViewModel"); }
        }

        #endregion
    }




public class EntityAddressViewModel: DependencyObject
    {
        public EntityAddressViewModel() { }
        public Address CurrentAddress
        {
            get { return (Address)GetValue(CurrentAddressProperty); }
            set { SetValue(CurrentAddressProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentAddress.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentAddressProperty =
            DependencyProperty.Register("CurrentAddress", typeof(Address), typeof(EntityAddressViewModel));

        public ICollectionView States
        {
            get { return (ICollectionView)GetValue(StatesProperty); }
            set { SetValue(StatesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for States.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatesProperty =
            DependencyProperty.Register("States", typeof(ICollectionView), typeof(EntityAddressViewModel));

        public ICollectionView AddressTypes
        {
            get { return (ICollectionView)GetValue(AddressTypesProperty); }
            set { SetValue(AddressTypesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AddressTypes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AddressTypesProperty =
            DependencyProperty.Register("AddressTypes", typeof(ICollectionView), typeof(EntityAddressViewModel));


        public bool InEditMode
        {
            get { return (bool)GetValue(InEditModeProperty); }
            set { SetValue(InEditModeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for InEditMode.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InEditModeProperty =
            DependencyProperty.Register("InEditMode", typeof(bool), typeof(EntityAddressViewModel), new UIPropertyMetadata(true));



        public bool AddressTypeIsVisible
        {
            get { return (bool)GetValue(AddressTypeIsVisibleProperty); }
            set { SetValue(AddressTypeIsVisibleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AddressTypeIsVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AddressTypeIsVisibleProperty =
            DependencyProperty.Register("AddressTypeIsVisible", typeof(bool), typeof(EntityAddressViewModel), new UIPropertyMetadata(true));       
    }

//###############
//Except from datatemplate for typeof EntityAddressViewModel
 <ComboBox Grid.Column="1" Height="25" Margin="4" Name="stateComboBox" VerticalAlignment="Top"
                             ItemsSource="{Binding Path=States, Mode=TwoWay}" DisplayMemberPath="StateProvinceCode"
                             SelectedValue="{Binding Path=CurrentAddress.StateProvince, Mode=TwoWay,                   UpdateSourceTrigger=PropertyChanged}"
                             IsSynchronizedWithCurrentItem="True" IsEnabled="{Binding Path=InEditMode}"
                             />


解决方案

Hi Greg,

According to what is included in here, I think that 

CustomerShipToViewModel raises the INotifyPropertyChanged.PropertyChanged event through calling OnPropertyChanged(...) method in the property setter:

public EntityAddressViewModel AddressViewModel
        {
            get { return _currentAddress; }
            set { _currentAddress = value; OnPropertyChanged("AddressViewModel"); }
        }

The EntityAddressViewModel class does not seem to implement INotifyPropertyChanged, it seems that it does not raise INotifyPropertyChanged.PropertyChanged when value changes, so the bound control is not updated.

I hope this will help. : )


这篇关于具有MVVM数据绑定的WPF ComboBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆