1

によって繰り返されている中にComboBox存在するesから値を取得する必要があります。そして、私はそれらを別のデータ構造に格納する必要があります、少なくとも私はそう思います。かなり簡単に聞こえますか?私はそれがそうであることを願っています、私はそれで一日中立ち往生しています。ObservableCollectionItemsControl

これが私の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で、私のViewModelで定義されています:

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

    ...
}

何であるかを尋ねる前に、それがとExternalClassを含むものであることを知ってください。VariableValues

ここに問題があります。を取得する必要がありますSelectedIndexComboBoxしたがって、現在のコードを変更しますSelectedIndex="0")。そして、もし私ExternalClassがそれらの値を含む必要があるのなら、私はSelectedIndexすでにそのフィールド(VariableValue)にアクセスできるので、それは簡単でしょう。しかし、私はそれらのint値が必要です

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

    ...
}

またはそのようなもの。SelectedIndicesとの両方を含むクイックラッパークラスを作成しましたが、2つのクラスではなく、が必要なIVCollectionため、明らかに機能しません。ItemsControlObservableCollectionObservableCollection

そして、ここでの質問の本当の本質は(私は間違っている可能性があります、それが私が尋ねている理由です)、私が現在いるStyle/の範囲外にあるプロパティにアクセスするにはどうすればよいですか(例)?コードビハインドで問題なく実行できます。DataTemplateIVCell

    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などでイベントコマンドを使用してみましたが、それは問題を延期するだけです。私はそれを解決する必要があります。またはそれを回避します。

4

3 に答える 3

2

これは私がそれを行う方法であり、選択した値のプロパティを作成します

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

SelectedItem次に、ComboBoxSelectedObjectプロパティにバインドします

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

これがお役に立てば幸いです

于 2013-02-08T21:24:23.607 に答える
1

これを実現する方法の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をプロパティとして公開し、SelectedIndexを別のプロパティとして公開するExternalClassのラッパークラスを使用します。これは、最も簡単でMVVMに適した方法です。

于 2013-02-08T21:47:56.480 に答える
0

@sleimanと@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}"/>
于 2013-02-11T18:08:07.573 に答える