簡體   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