在ObservableCollection中为ComboBox创建事件(选中/未选中)

时间:2013-12-03 14:04:44

标签: c# wpf mvvm

我对WPF& MVVM,我在面板上有3个CheckBox项,我需要每当用户点击其中一个时,将调用一个方法。此方法应检查3 CheckBox中的每一个的状态(其中一个是'已检查',哪个是'未选中')并使用此信息在TextBlock上显示一些文本。例如,如果所有3个都被选中,它将显示“A”,如果所有这些都是未选中则显示“B”。

我对此并不复杂,希望你能帮助我。

以下是XAML代码:

<StackPanel>
    <ItemsControl Margin="5" ItemsSource="{Binding Path=CheckBoxCollection, Mode=TwoWay}" >
         <ItemsControl.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding Path=CheckBoxValue, Mode=TwoWay}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    <TextBlock>Result Here</TextBlock>
</StackPanel>

以下是代码:

public class CheckBoxValue
{
    bool _theValue;

    public bool theValue
    {
        get
        {
            return _theValue;
        }

        set
        {
            _theValue = value;
        }
    }
}

public class myViewModel : ViewModelBase
{
    public ObservableCollection<CheckBoxValue> CheckBoxCollection { get; set; }

    public myViewModel( Some Parameters.... )
    {
        CheckBoxCollection = new ObservableCollection<CheckBoxValue>();

        CheckBoxCollection.Add(new CheckBoxValue { theValue = false });
        CheckBoxCollection.Add(new CheckBoxValue { theValue = false });
        CheckBoxCollection.Add(new CheckBoxValue { theValue = false });

        base.RaisePropertyChanged( () => CheckBoxCollection );
    }
}

2 个答案:

答案 0 :(得分:1)

我更进一步为所有类型的“可选择”事物定义可重用的ViewModel:

public class Selectable<T>: ViewModelBase //ViewModelBase should Implement NotifyPropertyChanged.
{
    private T _model;
    public T Model 
    {   get { return _model; }
        set 
        {
            _model = value;
            NotifyPropertyChange("Model");
        }
    }

    public Action OnIsSelectedChanged;

    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            NotifyPropertyChange("IsSelected");

            if (OnIsSelectedChanged != null)
                OnIsSelectedChanged();
        }
    }
 }

了解我在IsSelected更改后将如何使用Delegate,以便您可以在ViewModel级别处理选择更改:

public class CheckBoxValue: Selectable<string>
{
   //.. no need for any special stuff here
}

public class myViewModel : ViewModelBase
{
    public ObservableCollection<CheckBoxValue> CheckBoxCollection { get; set; }

    public myViewModel( Some Parameters.... )
    {
        CheckBoxCollection = new ObservableCollection<CheckBoxValue>();

        CheckBoxCollection.Add(new CheckBoxValue { Model = "CheckBox1" });
        CheckBoxCollection.Add(new CheckBoxValue { Model = "CheckBox2" });
        CheckBoxCollection.Add(new CheckBoxValue { Model = "CheckBox3" });
        //Setting IsSelected to false is redundant because bools default to false, so I removed that.

        //Calling NotifyPropertyChange in the constructor is also redundant because the object is just being constructed, therefore WPF did not even read the initial values from it yet.

       //Now, here we handle the Selection change:
       foreach (var item in CheckBoxCollection)
           item.OnIsSelectedChanged = OnCheckBoxSelectionChanged;
    }

    private void OnCheckBoxSelectionChanged()
    {
       //... etc    
    }    

XAML:

<!-- Two way binding to the ItemsSource property is redundant, it doesn't make sense. -->
<ItemsControl ItemsSource="{Binding Path=CheckBoxCollection}">
     <ItemsControl.ItemTemplate>
        <DataTemplate>

            <!-- CheckBox.IsChecked BindsToWayByDefault, so it is also redundant
                 See http://msdn.microsoft.com/en-us/library/system.windows.frameworkpropertymetadata.bindstwowaybydefault(v=vs.110).aspx -->

            <!-- Also see how I'm adding content to the CheckBox here -->

            <CheckBox Content="{Binding Model}"
                      IsChecked="{Binding Path=IsSelected}" />

        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

}

答案 1 :(得分:0)

我可能改变了太多但这可能是更简单的方法。

<StackPanel>
 <CheckBox IsChecked="{Binding Path=CheckBoxValue1, Mode=TwoWay}" />
 <CheckBox IsChecked="{Binding Path=CheckBoxValue2, Mode=TwoWay}" />
 <CheckBox IsChecked="{Binding Path=CheckBoxValue3, Mode=TwoWay}" />


 <TextBlock>
  <TextBlock.Text>
   <Binding Path="StringValue" UpdateSourceTrigger="PropertyChanged" />
  </TextBlock.Text>
 </TextBlock>
</StackPanel>





#region properties
    string stringValue;
    public StringValue
    {
    get {return stringValue;}
    set 
    {
     stringValue = value;
     OnPropertyChanged("StringValue");
    }

    }
    bool checkBoxValue1;
    public bool CheckBoxValue1
    {
        get{ return checkBoxValue1; }
        set
        {
             checkBoxValue1= value;
             ChangedValue();
        }
    }
    bool checkBoxValue2;
    public bool CheckBoxValue2
    {
        get{ return checkBoxValue2; }
        set
        {
             checkBoxValue2 = value;
             ChangedValue();
        }
    }
    bool checkBoxValue3;
    public bool CheckBoxValue3
    {
        get{ return checkBoxValue3; }
        set
        {
             checkBoxValue3 = value;
             ChangedValue();
        }
    }
#endregion

public class myViewModel : ViewModelBase
{


    public myViewModel( Some Parameters.... )
    {
        checkBoxValue1 = false;
        checkBoxValue2 = false;
        checkBoxValue3 = false;
        StringValue = b;

    }
    public void ChangedValue()
    {
      if (checkBoxValue1 && checkBoxValue2 && checkBoxValue3)
      {
          StringValue = a
      }
      else
      {
          StringValue = b
      }
    }
}

对不起,这有点被抛在一起,但希望你能得到这个想法