2015-03-30 48 views
0

我正在學習和創建我的第一個WPF應用程序試圖實現MVVM設計模式,但我似乎無法解決爲什麼此屬性不會解僱其設置訪問器,所以我可以使用我擁有的OnPropertyChanged方法。真的很感謝解釋,爲什麼這不能按我的預期工作。模型屬性沒有擊中集訪問器在WPF MVVM項目

我不明白的部分是在ViewModel的GetChargeUnits方法中,我創建了我的電荷單元模型的一個實例,並將該屬性設置爲讀者的結果(此讀者確實返回結果)該屬性設置好嗎?但是,在單步執行時,它不會在屬性中觸發Set行,因此我無法檢測它是否已更改。在這個方法中評論的部分是我最初嘗試過很多組合的原因。

請幫幫忙,謝謝

型號:

public class ChargeUnit : INotifyPropertyChanged 
{ 
    private string _chargeUnitDescription; 
    private int _chargeUnitListValueId; 
    public event PropertyChangedEventHandler PropertyChanged; 

    public ChargeUnit() 
    { 

    } 
    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public string ChargeUnitDescription 
    { 
     get { return _chargeUnitDescription; } 
     set 
     { 
      _chargeUnitDescription = value; 
      OnPropertyChanged("ChargeUnitDescription"); 
     } 
    } 

    public int ChargeUnitListValueId 
    { 
     get { return _chargeUnitListValueId; } 
     set 
     { 
      _chargeUnitListValueId = value; 
      OnPropertyChanged("ChargeUnitListValueId"); 
     } 
    } 

視圖模型:

public class ClientRatesViewModel 
{ 
    private IList<ClientRates> _clientRatesPreAwr; 
    private IList<ClientRates> _clientRatesPostAwr; 
    private List<ChargeUnit> _chargeUnits; 
    private const string _connectionString = @"connectionString...."; 
    public ClientRatesViewModel() 
    { 
     _clientRatesPreAwr = new List<ClientRates> 
     { 
      new ClientRates {ClientRatesPreAwr = "Basic"} 
     }; 

     _clientRatesPostAwr = new List<ClientRates> 
     { 
      new ClientRates{ClientRatesPostAwr = "Basic Post AWR"} 
     }; 

     _chargeUnits = new List<ChargeUnit>(); 
    } 

    public IList<ClientRates> ClientRatesPreAwr 
    { 
     get { return _clientRatesPreAwr; } 
     set { _clientRatesPreAwr = value; } 
    } 

    public IList<ClientRates> ClientRatesPostAwr 
    { 
     get { return _clientRatesPostAwr; } 
     set { _clientRatesPostAwr = value; } 
    } 

    public List<ChargeUnit> ChargeUnits 
    { 
     get { return _chargeUnits; } 
     set { _chargeUnits = value; } 
    } 

    public List<ChargeUnit> GetChargeUnits() 
    { 
     using (var connection = new SqlConnection(_connectionString)) 
     { 
      connection.Open(); 
      using (var command = new SqlCommand("SELECT LV.ListValueId, LV.ValueName FROM tablename", connection)) 
      { 
       command.CommandType = CommandType.Text; 

       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         var test = new ChargeUnit(); 
         test.ChargeUnitDescription = reader["ValueName"].ToString(); 
         //_chargeUnits.Add(new ChargeUnit 
         //{ 
         // ChargeUnitDescription = reader["ValueName"].ToString(), 
         // ChargeUnitListValueId = (int)reader["ListValueId"] 
         //}); 
        } 
       } 


      } 

     } 
     return new List<ChargeUnit>(); 
    } 
+1

,你檢查你的VS設置getter和setter方法?這是爲VS 2013,但你可能可以谷歌那個其他版本。 轉到工具 - >選項 - >調試 - >常規。 然後在右側取消選中「Step over properties and operators(Managed only)」 – 2015-03-30 20:23:02

+1

@FrankJ您破解了它!非常感謝 – 2015-03-30 20:47:15

+0

@FrankJ剛剛意識到這是問題的一部分,因爲當我將它設置在ViewModel中時,它已跳入集合中,但是當我更改組合框中的值時,我的模型中的ChargeUnitDescription屬性從未達到Set ,但是它總會返回我剛剛選擇的更新後的值? – 2015-03-31 14:56:17

回答

0

我認爲這是一個誤區。

想想那樣:爲什麼您的模型中的ChargeUnitDescription會發生變化?你不改變該財產的內容。

您所描述的是,您正在更改您的ComboBoxSelectedItem。您的模型實例的get get命中,因爲ComboBox需要訪問它以顯示字符串,因爲您在與ComboBoxDisplayMemberPath屬性綁定中定義它。

您感興趣的是SelectedItemSelectedValue(取決於您的設置)ComboBox

這裏是一個最小的例子來說明這一點:

namespace SOBindingTest1 
{ 
    public partial class MainWindow : Window 
    { 
     public ClientRatesViewModel crvm { get; set; } 
     public MainWindow() 
     { 
      InitializeComponent(); 
      crvm = new ClientRatesViewModel(); 
     } 


     public class ChargeUnit : INotifyPropertyChanged 
     { 
      private string _chargeUnitDescription; 
      private int _chargeUnitListValueId; 

      public ChargeUnit() 
      { 

      } 

      public string ChargeUnitDescription 
      { 
       get { return _chargeUnitDescription; } 
       set 
       { 
        _chargeUnitDescription = value; 
        OnPropertyChanged(); 
       } 
      } 

      public int ChargeUnitListValueId 
      { 
       get { return _chargeUnitListValueId; } 
       set 
       { 
        _chargeUnitListValueId = value; 
        OnPropertyChanged(); 
       } 
      } 

      public event PropertyChangedEventHandler PropertyChanged; 
      protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") 
      { 
       PropertyChangedEventHandler tmp = this.PropertyChanged; 
       if (tmp != null) 
       { 
        tmp(this, new PropertyChangedEventArgs(propertyName)); 
       } 
      } 
     } 

     public class ClientRatesViewModel : INotifyPropertyChanged 
     { 
      public ClientRatesViewModel() 
      { 
       _chargeUnits = new List<ChargeUnit>(); 
       for (int i = 0; i < 10; i++) 
       { 
        _chargeUnits.Add(new ChargeUnit() { ChargeUnitDescription = i.ToString(), ChargeUnitListValueId = i }); 
       } 
      } 

      protected ChargeUnit _SelectedItem; 
      public ChargeUnit SelectedItem 
      { 
       get 
       { 
        return this._SelectedItem; 
       } 
       set 
       { 
        if(this._SelectedItem == value) 
        { 
         return; 
        } 
        this._SelectedItem = value; 
        this.OnPropertyChanged(); 
       } 
      } 


      private List<ChargeUnit> _chargeUnits; 
      public List<ChargeUnit> ChargeUnits 
      { 
       get { return _chargeUnits; } 
       set 
       { 
        if(this._chargeUnits == value) 
        { 
         return; 
        } 
        _chargeUnits = value; 
        this.OnPropertyChanged(); 
       } 
      } 

      public event PropertyChangedEventHandler PropertyChanged; 
      protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") 
      { 
       PropertyChangedEventHandler tmp = this.PropertyChanged; 
       if (tmp != null) 
       { 
        tmp(this, new PropertyChangedEventArgs(propertyName)); 
       } 
      } 
     } 
    } 
} 

以及相應的XAML:

<Window x:Class="SOBindingTest1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:SOBindingTest1" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 
     <TextBlock Text="Bla:" HorizontalAlignment="Right" Margin="10"/> 
     <ComboBox Name="cboTest" Grid.Column="1" Margin="3" DisplayMemberPath="ChargeUnitDescription" SelectedValuePath="ChargeUnitListValueId" ItemsSource="{Binding Path=crvm.ChargeUnits, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}" SelectedItem="{Binding Path=crvm.SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/> 
    </Grid> 
</Window> 

UPDATE:

改變了代碼,使其充滿所選擇的項目成你的ViewModel的一個屬性。如果你在setter中放置了一個斷點,如果你在ComboBox中選擇了某些東西,它會被擊中。

對於您可能會問的未來問題,請提供一個Minimal, Complete, and Verifiable example並根據此問題提出相應的問題。這會節省很多時間。

更新2: 添加到INotifyPropertyChanged的ViewModel的例子

+0

感謝您的幫助Frank,但我在印象處理事件下不會遵循MVVM設計模式。我看到很多帖子都是有約束力的,當這個值改變屬性時他就是這個集合。 這似乎不起作用 http://stackoverflow.com/questions/21130850/selection-changed-event-of-combobox-in-wpf-mvvm – 2015-04-01 08:32:58