繁体   English   中英

具有多个模型实例的WPF MVVM

[英]WPF MVVM with multiple model instances

那里有很多MVVM例子,但是我无法将一个例子应用于我的案例,因为我有几个相同类的实例 另外,我需要直接操作模型,以便可以将某些观察者订阅到其可观察者。

我简化了问题的处理。 我的模型中有三个类:Lamp,Switch和Grid。 他们可以通过观察者/可观察机制进行交互。 基本上,激活开关可以打开/关闭连接到同一电网的所有灯。

我想创建一个窗口,显示这些类的特定用法。 Button应该绑定到Switch,而TextBlock应该绑定到Lamp。

如何将每个实例绑定到已为其准备的UI组件?

这是一个简单的案例,我想为构建一个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);

如果您想使用它,这是我的完整代码(VS 2017)

这个答案很难看,但是确实有用,也许可以帮助某人提供更好的东西。

我将暂时实施此解决方案。 也许,我将做一些更好的事情来处理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));
        }
    }
}

和接口IRelayCommand沿着类RelayCommand:

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);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM