有很多MVVM示例,但我不能在我的案例中应用一个,因为我有几个相同类的实例。此外,我需要直接操作模型,以便我可以将一些Observer订阅到它们的Observable。
我简化了我的问题。 我的模型中有三个类:Lamp,Switch和Grid。 它们可以通过Observer / Observable机制进行交互。 基本上,激活开关可以打开/关闭连接到同一网格的所有灯。
我想创建一个窗口,显示这些类的特定用法。应该将Button绑定到Lamp's和TextBlock绑定到Lamp的。
如何将每个实例绑定到我为其准备的UI组件?
这是一个简单的案例,我想为以下内容构建一个用户界面:
Grid entranceGrid = new Grid("Entrance Grid");
Lamp hallLamp = new Lamp("Hall Lamp");
Lamp stairsLamp = new Lamp("Stairs Lamp");
Switch downSwitch = new Switch("Downstair Switch");
Switch upSwitch = new Switch("Upstair Switch");
downSwitch.Subscribe(entranceGrid);
upSwitch.Subscribe(entranceGrid);
entranceGrid.Subscribe(hallLamp);
entranceGrid.Subscribe(stairsLamp);
// Below are four instances I'd like to bind to some UI component.
LampViewModel hallLampVM = new LampViewModel(hallLamp);
LampViewModel stairsLampVM = new LampViewModel(stairsLamp);
SwitchViewModel downSwitchVM = new downSwitchVM(downSwitch);
SwitchViewModel upSwitchVM = new downSwitchVM(upSwitch);
答案 0 :(得分:0)
这个答案很难看,但它确实有用,也许它会帮助别人找到更好的东西。
我暂时会实施这个解决方案。也许,我会更好地处理NotifyPropertyChanged。
窗口XAML:
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<Grid Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="3*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="Entrée">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Hall d'entrée"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Escalier"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TxtHallLamp}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding TxtStairsLamp}"/>
<Button Grid.Row="0" Grid.Column="2" Content="rez" Command="{Binding DownSwitchCommand}"/>
<Button Grid.Row="1" Grid.Column="2" Content="1er" Command="{Binding UpSwitchCommand}"/>
</Grid>
</GroupBox>
[Few lines you don't need]
</Grid>
MainViewModel上的ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public bool NotifyPropertyChanged<T>(ref T variable, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(variable, value)) return false;
variable = value;
NotifyPropertyChanged(propertyName);
return true;
}
}
class MainViewModel : ViewModelBase
{
private Lamp _HallLamp, _StairsLamp;
private Switch _DownSwitch, _UpSwitch;
private IRelayCommand _DownSwitchCommand, _UpSwitchCommand;
public MainViewModel()
{
#region entrance
Grid entranceGrid = new Grid("Entrance Grid");
_HallLamp = new Lamp("Hall Lamp");
_StairsLamp = new Lamp("Stairs Lamp");
_DownSwitch = new Switch("Downstair Switch");
_UpSwitch = new Switch("Upstair Switch");
_DownSwitch.Subscribe(entranceGrid);
_UpSwitch.Subscribe(entranceGrid);
entranceGrid.Subscribe(_HallLamp);
entranceGrid.Subscribe(_StairsLamp);
#endregion // entrance
}
private string LampToTxt(Lamp lamp)
{
return lamp.Light ? "ON" : "OFF";
}
public string TxtHallLamp
{
get
{
return LampToTxt(_HallLamp);
}
}
public string TxtStairsLamp
{
get
{
return LampToTxt(_StairsLamp);
}
}
private void NotifyEntranceGridPropertyChanged()
{
NotifyPropertyChanged(nameof(TxtHallLamp));
NotifyPropertyChanged(nameof(TxtStairsLamp));
}
public IRelayCommand DownSwitchCommand
{
get
{
return _DownSwitchCommand ?? (_DownSwitchCommand = new RelayCommand(
() => {
_DownSwitch.Press();
NotifyEntranceGridPropertyChanged();
},
() => true));
}
}
public IRelayCommand UpSwitchCommand
{
get
{
return _UpSwitchCommand ?? (_UpSwitchCommand = new RelayCommand(
() => {
_UpSwitch.Press();
NotifyEntranceGridPropertyChanged();
},
() => true));
}
}
}
沿着RelayCommand类的接口IRelayCommand:
public interface IRelayCommand : ICommand
{
void RaiseCanExecuteChanged();
}
class RelayCommand : IRelayCommand
{
private Action _Execute;
private Func<bool> _CanExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action Execute) : this(Execute, null)
{
}
public RelayCommand(Action Execute, Func<bool> CanExecute)
{
if (Execute == null)
throw new ArgumentNullException();
_Execute = Execute;
_CanExecute = CanExecute;
}
public bool CanExecute(object parameter)
{
return (_CanExecute == null) ? true : _CanExecute();
}
public void Execute(object parameter)
{
_Execute();
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}