2010-11-02 134 views
1

在Silverlight 4 + MVVM-Light工具包中出現問題並且在搜索網絡後沒有成功掙扎大約一週之後,我想在此展示我的問題,並希望有人可以給我有些提示。數據綁定Silverlight中的ComboBox與MVVM Light的問題

我想提出簡化PROGRAMM:

我的模型類:

  1. 公共類Person { 私人小數_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; } 
    } 
    

    }

  2. PersonInfo

    公共類PersonInfo { 私人小數_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; } 
    } 
    

    }

這裏我的視圖模型:

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類的實例,其中包含正確的插入文本在文本框中,但作爲組合框中選擇的值,我總是得到,獨立於我在組合框中選擇。這種情況只發生在我使用組合框項目實例的情況下。如果我使用組合框項目只是字符串值,則不會發生此問題。但我必須在我的組合框中使用一個類的實例。

我希望有人有提示。 謝謝!

PS:

有趣的仍然是事實,即改變ChoosenPerson從的分配時 「ChoosenPerson =新Model.PersonInfo();」到_choosenPerson = new Model.PersonInfo();這意味着通過使用私有成員進行賦值而不是訪問方法,第二次單擊該按鈕時,值會正確寫入按鈕的參數中。唯一的是,上次插入的值不會被刪除。它們在第一次按鈕點擊後顯示。但是,當通過訪問方法創建新的空ChoosenPerson時,它們不會顯示... 我無法解釋這種行爲。誰能幫我??謝謝。

回答

0

亞當在正確的軌道上。我會將您的PersonViewModel分配給DataContext,而不是將其分配給ChoosenPerson

<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" 
    DataContext="{Binding Source={StaticResource Locator}, Path=PersonViewModel}" 
    mc:Ignorable="d" 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 AllPerson}" DisplayMemberPath="Des_Person" SelectedValuePath="Cod_Person" SelectedItem="{Binding Path=ChoosenPerson, Mode=TwoWay}" /> 
     <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="159,199,0,0" Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding save_Click}" CommandParameter="{Binding SelectedItem, ElementName=comboBox1}" /> 
     <TextBox Height="23" HorizontalAlignment="Left" Margin="94,107,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding ChoosenPerson.Des_Person, Mode=TwoWay}" /> 
    </Grid> 
</UserControl> 

我也完全擺脫了PersonInfo類。你不需要這個班。您可以直接使用Person對象。將您的參考文獻從PersonInfo更改爲Person類。另外,如果要清除ComboBox中的當前選擇,請將ChoosenPerson屬性設置爲空。不要新建一個類的實例。 ChoosenPerson屬性需要爲null或AllPerson集合中的一個對象。

public class PersonViewModel : ViewModelBase 
{ 
    public RelayCommand<Person> save_Click { get; private set; } 

    public PersonViewModel() 
    { 
     save_Click = new RelayCommand<Person>(personInfo => 
     { 
      SavePerson(personInfo); 
     }); 

     //the content of the combo box is defined 
     AllPerson = new ObservableCollection<Person> 
     { 
      new Person(){ 
       Cod_Person = 1, 
       Des_Person = "Name 1" 
      }, 
      new Person(){ 
       Cod_Person = 2, 
       Des_Person = "Name 2" 
      } 
     }; 

     //an empty PersonInfo is created, which the UI will work on 
     ChoosenPerson = new Person(); 
    } 

    private void SavePerson(Person personInfo) 
    { 
     //here some safing processing could be done... 
     //but is omitted here 


     //and here a new PersonInfo is assigned the ChoosenPerson 
     ChoosenPerson = null; 
    } 

    public const string AllPersonPropertyName = "AllPerson"; 
    private ObservableCollection<Person> _allPersons = null; 
    public ObservableCollection<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 Person _choosenPerson = null; 
    public Person 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); 
     } 
    } 
} 
+0

謝謝你的幫助,現在一切正常了,問題是一方面是DataBinding,另一方面是我的Classes,填充組合框必須實現IEquatable接口.... – WillCoer 2010-11-03 14:41:10

0

我想你想是這樣的:

<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}" 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 AllPerson}" DisplayMemberPath="Des_Person" SelectedValuePath="Cod_Person" SelectedValue="{Binding Path=ChoosenPerson, Mode=TwoWay}" /> 
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="159,199,0,0" Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding save_Click}" CommandParameter="{Binding ChoosenPerson}" /> 
    <TextBox Height="23" HorizontalAlignment="Left" Margin="94,107,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Des_note, Mode=TwoWay}" /> 
</Grid> 

我大部分的綁定更新。一旦設置了UserControl的數據上下文,其餘的控件就可以簡單地引用屬性名稱,而不必使用定位器。我也認爲你有幾件事指向錯誤的地方。

+0

這不起作用。首先將文本框設置爲上面設置的DataContext中不存在的Path Des_note。第二個組合框的SelectedValue被設置爲路徑ChoosenPerson,其具有PersonInfo類型,但是SelectedValuePath被設置爲具有十進制類型的Cod_Person。問題一定是別的。 – WillCoer 2010-11-02 13:59:19

+0

我現在看到了。看起來你需要修改你的ViewModel來跟蹤當前Person以及相應的PersonInfo。你真的想將UserControl的DataContext設置爲ViewModel本身 - 我在原始答案中試圖做的主要觀點。這將真正簡化事情。 ViewModel是視圖的模型 - 其中的屬性和方法應該與View中的控件非常接近。 – 2010-11-02 14:13:25

+0

好吧,你認爲是這樣的: ... DataContext =「{Binding Source = {StaticResource Locator},Path = PersonViewModel} ..