感谢Rachel的评论,下面是我的答案。我希望这能帮助那些需要此操作的人。我搜寻了许多,没有发现明确写下的例子。或许这太简单了,不值得去费力 :) 我发现整合所有东西并使其运作起来有些困难,所以在这里记录下来。再次感谢Rachel!
<Window x:Class="Demo.MainWindow"
xmlns="http:
xmlns:x="http:
xmlns:local="clr-namespace:Demo"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Number Of Players" ItemsSource="">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="" />
<Setter Property="IsCheckable" Value="True" />
<Setter Property="IsChecked" Value="" />
<Setter Property="Command" Value="}}" />
<Setter Property="CommandParameter" Value="" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</Menu>
<Grid>
</Grid>
</DockPanel>
以下是ViewModel代码:
namespace Demo.ViewModel
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
_myCollection = new ObservableCollection<NumberOfPlayersClass>();
foreach (NumberOfPlayersEnum value in Enum.GetValues(typeof(NumberOfPlayersEnum)))
{
NumberOfPlayersClass myClass = new NumberOfPlayersClass();
myClass.Player = value;
myClass.IsChecked = value == NumberOfPlayersEnum.Two ? true : false;
myClass.Title = Enum.GetName(typeof(NumberOfPlayersEnum), value);
_myCollection.Add(myClass);
}
}
private ICommand _myCommand;
public ICommand MyCommand
{
get
{
if (_myCommand == null)
{
_myCommand = new RelayCommand(new Action<object>(ResolveCheckBoxes));
}
return _myCommand;
}
}
ObservableCollection<NumberOfPlayersClass> _myCollection = new ObservableCollection<NumberOfPlayersClass>();
public ObservableCollection<NumberOfPlayersClass> MyCollection
{
get
{
return _myCollection;
}
}
public enum NumberOfPlayersEnum
{
One = 1,
Two =2,
Three =3,
}
public class NumberOfPlayersClass : ViewModelBase
{
public NumberOfPlayersClass()
{
IsChecked = false;
}
public NumberOfPlayersEnum Player { get; set; }
private bool _isChecked = false;
public bool IsChecked
{ get
{ return _isChecked;
}
set
{
_isChecked = value;
OnPropertyChanged("IsChecked");
}
}
public string Title { get; set; }
}
private void ResolveCheckBoxes(object checkBoxNumber)
{
NumberOfPlayersEnum myEnum = (NumberOfPlayersEnum)checkBoxNumber;
ObservableCollection<NumberOfPlayersClass> collection = MyCollection;
NumberOfPlayersClass theClass = collection.First<NumberOfPlayersClass>(t => t.Player == myEnum);
foreach (NumberOfPlayersClass iter in collection)
{
iter.IsChecked = false;
}
theClass.IsChecked = true;
}
}
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
#region Constructor
protected ViewModelBase()
{
}
#endregion // Constructor
#region DisplayName
public virtual string DisplayName { get; protected set; }
#endregion // DisplayName
#region Debugging Aides
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
#region IDisposable Members
public void Dispose()
{
this.OnDispose();
}
protected virtual void OnDispose()
{
}
#if DEBUG
~ViewModelBase()
{
string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
System.Diagnostics.Debug.WriteLine(msg);
}
#endif
#endregion // IDisposable Members
}
你可以在以下网址获取关于RelayCommand和ViewModelBase类的信息:
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 和
http://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/。
Menu.ItemsSource
绑定到一个ObservableCollection<T>
上吗?其中<T>
是一个包含IsChecked
属性的类,可以将其绑定到MenuItem.IsChecked
上。然后,为集合中的每个项附加一个 PropertyChange 通知,告诉它当IsChecked
更改为 true 时,将集合中的所有其他项设置为IsChecked=false
。 - Rachel