使用 MVVM Light 在 Silverlight 中对组合框进行数据绑定的问题
在与 Silverlight 4 + MVVM-Light 工具包中的问题斗争了大约一周之后,在网上搜索但没有成功之后,我想在这里提出我的问题,并希望有人能给我一些提示。
我想展示简化的程序:
我的模型类:
Person
公共类人 { 私有小数_cod_Person;
公共十进制 Cod_Person { 获取{返回_cod_Person; } 设置 { _cod_Person = 值; } } 私有字符串_des_Person; 公共字符串 Des_Person { 得到{返回_des_Person; } 设置 { _des_Person = 值; } }
}
人员信息
公共类PersonInfo { 私人小数_cod_person;
公共十进制 Cod_person { 得到{返回_cod_person; } 设置 { _cod_person = 值; } } 私有字符串_des_note; 公共字符串 Des_note { 得到{返回_des_note; } 设置 { _des_note = 值; } }
}
是我的 ViewModel:
public class PersonViewModel : ViewModelBase
{
public RelayCommand<Model.PersonInfo> save_Click { get; private set; }
public PersonViewModel()
{
save_Click = new RelayCommand<Model.PersonInfo>(personInfo =>
{
SavePerson(personInfo);
});
//the content of the combo box is defined
AllPerson = new ObservableCollection<Model.Person>
{
new Model.Person(){
Cod_Person = 1,
Des_Person = "Name 1"
},
new Model.Person(){
Cod_Person = 2,
Des_Person = "Name 2"
}
};
//an empty PersonInfo is created, which the UI will work on
ChoosenPerson = new Model.PersonInfo();
}
private void SavePerson(Model.PersonInfo personInfo)
{
//here some safing processing could be done...
//but is omitted here
//and here a new PersonInfo is assigned the ChoosenPerson
ChoosenPerson = new Model.PersonInfo();
}
public const string AllPersonPropertyName = "AllPerson";
private ObservableCollection<Model.Person> _allPersons = null;
public ObservableCollection<Model.Person> AllPerson
{
get
{
return _allPersons;
}
set
{
if (_allPersons == value)
{
return;
}
var oldValue = _allPersons;
_allPersons = value;
RaisePropertyChanged(AllPersonPropertyName, oldValue, value, true);
}
}
public const string ChoosenPersonPropertyName = "ChoosenPerson";
private Model.PersonInfo _choosenPerson = null;
public Model.PersonInfo ChoosenPerson
{
get
{
return _choosenPerson;
}
set
{
if (_choosenPerson == value)
{
return;
}
var oldValue = _choosenPerson;
_choosenPerson = value;
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(ChoosenPersonPropertyName, oldValue, value, true);
}
}
}
在我的视图 (PersonView) 中,我有一个组合框、一个文本框和一个按钮:
<UserControl x:Class="TEST_STACKOVERFLOW.PersonView"
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"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=PersonViewModel.ChoosenPerson}" d:DesignHeight="258" d:DesignWidth="341">
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="84,51,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Source={StaticResource Locator}, Path=PersonViewModel.AllPerson}" DisplayMemberPath="Des_Person" SelectedValuePath="Cod_Person" SelectedValue="{Binding Path=Cod_person, Mode=TwoWay}" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="159,199,0,0" Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding Source={StaticResource Locator}, Path=PersonViewModel.save_Click}" CommandParameter="{Binding}" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="94,107,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Des_note, Mode=TwoWay}" />
</Grid>
第一次单击按钮时,一切正常。单击按钮后传递的参数(PersonInfo)包含所选的 ComboBox 值(Cod_person)和插入的文本(Des_note)。在 SavePerson 方法中,一个新的 PersonInfo 实例被分配给 ChoosenPerson 对象。当我第二次单击该按钮时,出现问题。然后,作为单击按钮后的参数,我得到一个 PersonInfo 类的实例,其中包含文本框中正确插入的文本,但作为在组合框中选择的值,我总是得到 0,与我的内容无关在组合框中选择。这个问题发生在我用作类的组合框项目实例的情况下。如果我仅使用字符串值作为组合框项目,则不会出现此问题。但我必须在组合框中使用类的实例。
我希望有人有提示。 谢谢!
PS:
有趣的事实仍然是,当从“ChoosenPerson = new Model.PersonInfo();”更改 ChoosenPerson 的分配时to _choosenPerson = new Model.PersonInfo(); 这意味着通过使用私有成员而不是访问方法进行分配,第二次单击按钮时,值将正确写入按钮的参数中。唯一的问题是上次插入的值没有被删除。它们在第一次单击按钮后显示。但是当通过访问方法分配新的空 ChoosenPerson 时,它们不会显示...... 我无法解释这种行为。谁能帮助我?谢谢。
After struggling for about one week with a problem in Silverlight 4 + MVVM-Light toolkit and after searching the web without success I want to present my problem here and hope that somebody could give me some hints.
I want to present the simplified programm:
My model classes:
Person
public class Person
{
private decimal _cod_Person;public decimal Cod_Person { get { return _cod_Person; } set { _cod_Person = value; } } private string _des_Person; public string Des_Person { get { return _des_Person; } set { _des_Person = value; } }
}
PersonInfo
public class PersonInfo
{
private decimal _cod_person;public decimal Cod_person { get { return _cod_person; } set { _cod_person = value; } } private string _des_note; public string Des_note { get { return _des_note; } set { _des_note = value; } }
}
Here my ViewModel:
public class PersonViewModel : ViewModelBase
{
public RelayCommand<Model.PersonInfo> save_Click { get; private set; }
public PersonViewModel()
{
save_Click = new RelayCommand<Model.PersonInfo>(personInfo =>
{
SavePerson(personInfo);
});
//the content of the combo box is defined
AllPerson = new ObservableCollection<Model.Person>
{
new Model.Person(){
Cod_Person = 1,
Des_Person = "Name 1"
},
new Model.Person(){
Cod_Person = 2,
Des_Person = "Name 2"
}
};
//an empty PersonInfo is created, which the UI will work on
ChoosenPerson = new Model.PersonInfo();
}
private void SavePerson(Model.PersonInfo personInfo)
{
//here some safing processing could be done...
//but is omitted here
//and here a new PersonInfo is assigned the ChoosenPerson
ChoosenPerson = new Model.PersonInfo();
}
public const string AllPersonPropertyName = "AllPerson";
private ObservableCollection<Model.Person> _allPersons = null;
public ObservableCollection<Model.Person> AllPerson
{
get
{
return _allPersons;
}
set
{
if (_allPersons == value)
{
return;
}
var oldValue = _allPersons;
_allPersons = value;
RaisePropertyChanged(AllPersonPropertyName, oldValue, value, true);
}
}
public const string ChoosenPersonPropertyName = "ChoosenPerson";
private Model.PersonInfo _choosenPerson = null;
public Model.PersonInfo ChoosenPerson
{
get
{
return _choosenPerson;
}
set
{
if (_choosenPerson == value)
{
return;
}
var oldValue = _choosenPerson;
_choosenPerson = value;
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(ChoosenPersonPropertyName, oldValue, value, true);
}
}
}
In my view (PersonView) I have a combo box, a text box and a button:
<UserControl x:Class="TEST_STACKOVERFLOW.PersonView"
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"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=PersonViewModel.ChoosenPerson}" d:DesignHeight="258" d:DesignWidth="341">
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="84,51,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Source={StaticResource Locator}, Path=PersonViewModel.AllPerson}" DisplayMemberPath="Des_Person" SelectedValuePath="Cod_Person" SelectedValue="{Binding Path=Cod_person, Mode=TwoWay}" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="159,199,0,0" Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding Source={StaticResource Locator}, Path=PersonViewModel.save_Click}" CommandParameter="{Binding}" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="94,107,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Des_note, Mode=TwoWay}" />
</Grid>
When the button is clicked the first time everything works. The parameter (PersonInfo) passed after the button was clicked contains the selected ComboBox value (Cod_person) and the inserted text(Des_note). In the method SavePerson a new PersonInfo instance is assigned to the ChoosenPerson object. The problem occurs when I click the button a second time. Then as parameter after the button was clicked I get an instance of the PersonInfo class which contains the correct inserted text in the text box but as value selected in the combo box I always get 0, independet of what I choosed in the combo box. This problems occurs just in the case, that I use as combo box items instances of a class. If I use as combo box items just string values this problem does not occur. But I have to use instances of a class in my combo box.
I hope that somebody has a hint.
Thanks!
PS:
Interesting is still the fact, that when changing the assignment of the ChoosenPerson from "ChoosenPerson = new Model.PersonInfo();" to _choosenPerson = new Model.PersonInfo(); this means by assignment through use of private members instead of access methods, the second time the button is clicked, the values are written into the parameter of the button correctly. The only thing is that the values that were inserted the last time are not deleted. They are shown after the first button click. But they are not shown when the assignment of a new empty ChoosenPerson is made throuh access methods...
I can't explain this behavior. Who can help me?? Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
亚当走在正确的道路上。我会将您的
PersonViewModel
分配给DataContext
,而不是将其分配给ChoosenPerson
。我也会完全摆脱
PersonInfo
类。你不需要这门课。您可以直接使用Person
对象。将引用从PersonInfo
更改为Person
类。另外,如果您想清除 ComboBox 中的当前选择,请将ChoosenPerson
属性设置为 null。不要新建类的实例。ChoosenPerson
属性必须为 null 或AllPerson
集合中的对象之一。Adam was on the right track. I would assign your
PersonViewModel
to theDataContext
instead of assigning it to theChoosenPerson
.I would also totally get rid of the
PersonInfo
class. You do not need this class. You can work with thePerson
object directly. Change your references fromPersonInfo
to thePerson
class. Also, if you want to clear out the current selection in theComboBox
, set theChoosenPerson
property to null. Do not new up an instance of a class. TheChoosenPerson
property needs to either be null or one of the objects in theAllPerson
collection.我想你想要这样的东西:
我更新了大部分绑定。一旦设置了 UserControl 的数据上下文,内部的其余控件就可以简单地引用属性名称,而不必使用定位器。我还认为你有一些事情指向了错误的地方。
I think you want something like this:
I updated most of the bindings. Once you set the UserControl's data context, the rest of the controls inside can simply reference the property name, instead of having to use the Locator. I also think you had a few things pointing to the wrong places.