2013-02-08 111 views
1

我需要從我的ComboBox es中獲取值,該值位於ObservableCollection中,並被ItemsControl重複執行。我需要將它們存儲在一個單獨的數據結構中,至少我認爲我是這樣做的。聽起來很直截了當?我希望是這樣,我一整天都被困住了。ItemsControl DataTemplate中的WPF MVVM訪問元素

這裏是我的XAML:

<Window.Resources> 
    <Style x:Key="IVCell" TargetType="{x:Type ItemsControl}"> 
     <Setter Property="ItemTemplate"> 
      <Setter.Value> 
       <DataTemplate> 
        <StackPanel> 
         <TextBlock Text="{Binding Variable.Name}"/> 
         <ComboBox x:Name="IVValues" ItemsSource="{Binding Values}" 
            SelectedIndex="0"/> 
        </StackPanel> 
       </DataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

... 
     <ItemsControl Name="IndependentVariables" Style="{StaticResource IVCell}" ItemsSource="{Binding IVCollection}"/> 

其中IVCollection在這裏被定義,在我的視圖模型:

public class MainViewModel : ViewModelBase 
{ 
    public ObservableCollection<ExternalClass> IVCollection { get; set; } 

    ... 
} 

之前你問什麼ExternalClass是,知道那是什麼包含VariableValues

這是問題所在。我需要得到ComboBoxSelectedIndex(所以我會改變當前的代碼SelectedIndex="0")。如果我的ExternalClass是需要包含這些值的,那很容易,因爲我已經可以訪問其字段(VariableValue)。但我需要那些int值在

public class MainViewModel : ViewModelBase 
{ 
    public ObservableCollection<int> SelectedIndices { get; set; } 

    ... 
} 

或類似的東西。我已經做了一個快速的包裝類,以包含SelectedIndicesIVCollection,但顯然這是行不通的,因爲ItemsControl想要ObservableCollection,而不是一個有兩個ObservableCollection s的類。

而且我在這裏想這個問題的真正的肉(我可能是錯的,這就是爲什麼我問)是怎樣訪問這就是Style/DataTemplate我目前的能力範圍以外的財產(例如IVCell)?我可以在沒有任何問題的代碼後面這樣做,像這樣,

private void IVValues_OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     for (var i = 0; i < IndependentVariables.Items.Count; i++) 
     { 
      var uiElement = IndependentVariables.ItemContainerGenerator.ContainerFromIndex(i); 
      var cBox = FindVisualChild<ComboBox>(uiElement); //Homebrew method 
      //cBox.SelectedIndex 
     } 
    } 

但我再次試圖保持MVVM友好。我甚至嘗試過使用MVVM Light等事件命令,但這只是推遲了這個問題。我需要解決它。或者規避它。

+0

所以,如果你管理的每個組合框的選定索引值綁定到你將selectedIndices集合,你將如何跟蹤它的值從組合框/ ExternalClass來到?這聽起來可能是IVCollection中的項目的長度是固定的,因此你的意圖是使用SelectedIndices中的值的索引,但我不完全清楚。 – 2013-02-08 21:37:31

+0

在'ExternalClass'中需要另外一個或兩個屬性來綁定ComboBox的SelctedItem和/或SelectedIndex以跟蹤哪些項目被選中。 – 2013-02-08 21:54:29

回答

0

@sleiman and @Brandon 您的答案都不是100%,但他們仍然非常有幫助。我使用了你的兩個答案中的元素來達到我的解決方案,所以我毫不猶豫地接受了一個。

我使用的包裝類溶液和暴露的屬性溶液(具有半無關,但仍然有必要事件處理技術一起)的組合,以創建以下:

public class IVWrapper : INotifyPropertyChanged 
{ 
    public VariableValueList<double> IVCollection { get; set; } 
    private int selectedIndex; 
    public int SelectedIndex 
    { 
     get { return selectedIndex; } 
     set 
     { 
      selectedIndex = value; 
      OnPropertyChanged("SelectedIndex"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 

     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class MainViewModel : ViewModelBase 
{ 

    public ObservableCollection<IVWrapper> IVWrapperCollection { get; set; } 

    ... 

    private void InitializeIVs() 
    { 
     IVWrapperCollection.Clear(); 
     foreach (var iv in ...) 
     { 
      var toBeAdded = new IVWrapper {IVCollection = iv}; 
      toBeAdded.PropertyChanged += (sender, args) => Foo(); 
      IVWrapperCollection.Add(toBeAdded); 
     } 
    } 

    public void Foo() 
    { 
     //Doin stuffs 
    } 
} 

與我的ViewModel的這種額外集成允許我在每次我的selectionIndex更改時調用一個函數。整齊!乾淨!

在XAML的MainView相應的變化:

    <StackPanel> 
         <TextBlock Text="{Binding IVCollection.Variable.Name}"/> 
         <ComboBox ItemsSource="{Binding IVCollection.Values}" 
            SelectedIndex="{Binding SelectedIndex}"/> 
        </StackPanel> 

... 

     <ItemsControl Name="IndependentVariables" Style="{StaticResource IVCell}" ItemsSource="{Binding IVWrapperCollection}"/> 
2

這是我會怎麼做,我想創建一個屬性選擇的值

// within the MainViewModel class 
private ExternalClass _selectedObject; 
public ExternalClass SelectedObject 
{ 
    get { return _selectedObject; } 
    set 
     { 
      _selectedObject= value; 
      RaisePropertyChanged("SelectedObject"); 
     } 
    } 

然後在ComboBox綁定SelectedItemSelectedObject財產

<ComboBox ItemsSource="{Binding IVCollection}" SelectedItem="{Binding SelectedObject}" > 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       ... data template goes here 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
</ComboBox> 

希望這將是有幫助

+1

'IVCollection'是一個集合的集合。 'IVCollection'中的每個項目都與ComboBox綁定;換句話說,ComboBox不會綁定到'IVCollection',至少如OP所述。 – 2013-02-08 21:57:10

+0

@MetroSmurf你是對的。 'IVCollection'中的每個項目都包含一個獨立變量,其中每個IV都包含其名稱以及其可能的值列表。根據這個答案,我需要一個數組或列表的SelectedObject,可以解析每個ComboBox的選定值。 – Joseph 2013-02-11 13:52:35

1

以下是可以完成的一種方法,雖然它不比您的示例更適合MVVM。

在主窗口,添加某處以下路由事件處理程序會顯示您的觀點之前,像構造或加載事件:

AddHandler(Selector.SelectionChangedEvent, new SelectionChangedEventHandler(OnSelectionChanged)); 

然後添加此處理程序:

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    var comboBox = e.OriginalSource as ComboBox; 
    if (comboBox == null) return; 
    var context = comboBox.DataContext as ExternalClass; 
    if (context == null) return; 
    var indexOfContext = IVCollection.IndexOf(context); 
    if (indexOfContext < 0) return; 
    SelectedIndices[indexOfContext] = comboBox.SelectedIndex; 
} 

我仍然不確定您計劃如何跟蹤哪些SelectedIndex與哪些數據一起使用,因此在上面的示例中,我假定SelectedIndices的長度是固定的。

如果您正在尋找一個純數據綁定解決方案,我強烈建議您只需將一個屬性放在ExternalClass上並綁定到它。或者,如果你反對,使用一個圍繞ExternalClass的包裝類,它將ExternalClass作爲一個屬性公開,而SelectedIndex作爲另一個。這將是最簡單和最MVVM友好的方式。

+0

謝謝你的回答。至於純數據綁定解決方案,我真的不能,因爲我不能僅僅爲了這種情況而修改外部類。否則,我很早以前就已經這麼做了!至於包裝類解決方案,如果你提到我的問題,你會看到我嘗試過。問題是'ItemsControl'想要一個'ObservableCollection',而不是包含'IVCollection'和'SelectedObject'的自定義類。另一方面,如果我把'IVCollection'變成'ObservableCollection ',現在我不知道如何訪問'ExternalClass'的變量和值。 – Joseph 2013-02-11 14:08:39