绑定附加属性和视图模型在MVVM | WPF

huangapple go评论72阅读模式
英文:

Binding attached properties and view models in MVVM | WPF

问题

以下是您要翻译的内容:

"HomeButtonViewModel" 类:

public class HomeButtonViewModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler? PropertyChanged;

    private double canvasTop;

    public double CanvasTop {
        get => canvasTop;
        set {
            canvasTop = value;
            OnPropertyChanged(nameof(CanvasTop));
        }
    }

    public void OnPropertyChanged([CallerMemberName] string name = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

"UserSettingsButtonViewModel" 类与之类似:

public class UserSettingsButtonViewModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler? PropertyChanged;

    private double canvasTop = 102;
    private double canvasLeft = -1;

    public double CanvasTop {
        get => canvasTop;
        set {
            canvasTop = value;
            OnPropertyChanged(nameof(CanvasTop));
        }
    }

    public double CanvasLeft {
        get => canvasLeft;
        set {
            canvasLeft = value;
            OnPropertyChanged(nameof(canvasLeft));
        }
    }

    public void OnPropertyChanged([CallerMemberName] string name = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

在单击按钮 "Change" 时更改这些属性的代码:

private void changeButton_Click(object sender, RoutedEventArgs e) {
    bool mode = !(bool)Settings.Default["mode7"];
    Settings.Default["mode7"] = mode;
    Settings.Default.Save();
    var h = new HomeButtonViewModel() {
        CanvasTop = mode ? 1 : 0
    };
    var us = new UserSettingsButtonViewModel() {
        CanvasTop = mode ? 102 : double.NaN,
        CanvasLeft = mode ? -1 : double.NaN
    };
}

请注意,我已将HTML实体转义字符还原为原始字符,以便更好地呈现代码。如果您需要进一步的帮助或解决其他问题,请告诉我。

英文:

There's my project tree:

MRE_WPF
|
--ViewModels
  |
  --MainWindowButtons
    |
    --HomeButtonViewModel.cs
    --UserSettingsButtonViewModel.cs
--MainWindow.xaml
--MainWindow.xaml.cs

I have three buttons on main window.

<Window x:Class="MRE_WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MRE_WPF"
        xmlns:main_window_buttons="clr-namespace:MRE_WPF.ViewModels.MainWindowButtons"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas Height="480" Name="MainCanvas">
        <Button x:Name="homeButton" 
                Height="55" 
                Width="75" 
                Background="#FF334166" 
                Foreground="{x:Null}" 
                FontSize="24" 
                BorderBrush="{x:Null}" 
                FontFamily="Tahoma"
                Canvas.Top="{Binding Path=(main_window_buttons:HomeButtonViewModel.CanvasTop), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
                >
            <TextBlock Text="Home" Foreground="White"/>
        </Button>

        <Button x:Name="userSetingsButton" 
                Height="55"
                Width="75"
                Background="#FF334166"
                Foreground="{x:Null}"
                FontSize="20"
                BorderBrush="{x:Null}"
                FontFamily="Tahoma"
                Canvas.Top="{Binding Path=(main_window_buttons:UserSettingsButtonViewModel.CanvasTop), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
                Canvas.Left="{Binding Path=(main_window_buttons:UserSettingsButtonViewModel.CanvasLeft), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
                >
            <TextBlock Text="User set" Foreground="White"/>
        </Button>

        <Button x:Name="changeButton" 
                Height="55" 
                Width="75" 
                Background="#FF334166" 
                Foreground="{x:Null}" 
                FontSize="20" 
                Click="changeButton_Click" 
                BorderBrush="{x:Null}" 
                FontFamily="Tahoma" 
                Canvas.Top="100"
                Canvas.Left="500">
            <TextBlock Text="Change" Foreground="White"></TextBlock>
        </Button>
    </Canvas>
</Window>

HomeButtonViewModel class:

public class HomeButtonViewModel:INotifyPropertyChanged {
    public event PropertyChangedEventHandler? PropertyChanged;

    private double canvasTop;

    public double CanvasTop {
        get => canvasTop;
        set {
            canvasTop = value;
            OnPropertyChanged(nameof(CanvasTop));
        }
    }

    public void OnPropertyChanged([CallerMemberName] string name = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

UserSettingsButtonViewModel is pretty much the same:

public class UserSettingsButtonViewModel:INotifyPropertyChanged {
    public event PropertyChangedEventHandler? PropertyChanged;

    private double canvasTop = 102;
    private double canvasLeft = -1;

    public double CanvasTop {
        get => canvasTop;
        set {
            canvasTop = value;
            OnPropertyChanged(nameof(CanvasTop));
        }
    }

    public double CanvasLeft {
        get => canvasLeft;
        set {
            canvasLeft = value;
            OnPropertyChanged(nameof(canvasLeft));
        }
    }

    public void OnPropertyChanged([CallerMemberName] string name = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

I want to change those properties on click on button Change:

private void changeButton_Click(object sender, RoutedEventArgs e) {
    bool mode = !(bool)Settings.Default["mode7"];
    Settings.Default["mode7"] = mode;
    Settings.Default.Save();
    var h = new HomeButtonViewModel() {
        CanvasTop = mode ? 1 : 0
    };
    var us = new UserSettingsButtonViewModel() {
        CanvasTop = mode ? 102 : double.NaN,
        CanvasLeft = mode ? -1 : double.NaN
    };
}

But on click nothing happens. I know that I do something wrong, but I don't know what.

//Also I want use command instead of Click, but let's solve one problem per question.

答案1

得分: 2

以下是您要翻译的内容:

"It's unclear why you have two view models.

Anyway, you should set the DataContext of the window to an instance of a single view model. In this once you could then initialize the child view models:

public class MainWindowVieModel
{
public HomeButtonViewModel HomeButtonViewModel { get; }
= new HomeButtonViewModel();

public UserSettingsButtonViewModel UserSettingsButtonViewModel { get; } 
    = new UserSettingsButtonViewModel();

}

You could then bind to the child view models through the main view model/DataContext in the view using the following syntax:

Finally, you need to set the properties of the view model instance(s) that you actually bind to in the code-behind of the window (where you should also set the DataContext of the window):

public partial class MainWindow : Window
{
private readonly MainWindowVieModel _viewModel = new MainWindowVieModel();

public MainWindow()
{
    InitializeComponent();
    DataContext = _viewModel;
}

private void changeButton_Click(object sender, RoutedEventArgs e)
{
    bool mode = !(bool)Settings.Default["mode7"];
    Settings.Default["mode7"] = mode;
    Settings.Default.Save();

    _viewModel.HomeButtonViewModel.CanvasTop = mode ? 1 : 0;

    _viewModel.UserSettingsButtonViewModel.CanvasTop = mode ? 102 : double.NaN;
    _viewModel.UserSettingsButtonViewModel.CanvasLeft = mode ? -1 : double.NaN;
}

}"

请注意,代码中的 HTML 编码已被还原为原始文本。

英文:

It's unclear why you have two view models.

Anyway, you should set the DataContext of the window to an instance of a single view model. In this once you could then initialize the child view models:

public class MainWindowVieModel
{
    public HomeButtonViewModel HomeButtonViewModel { get; } 
        = new HomeButtonViewModel();

    public UserSettingsButtonViewModel UserSettingsButtonViewModel { get; } 
        = new UserSettingsButtonViewModel();
}

You could then bind to the child view models through the main view model/DataContext in the view using the following syntax:

<Button x:Name="homeButton" 
                Height="55" 
                Width="75" 
                Background="#FF334166" 
                Foreground="{x:Null}" 
                FontSize="24" 
                BorderBrush="{x:Null}" 
                FontFamily="Tahoma"
                Canvas.Top="{Binding HomeButtonViewModel.CanvasTop}"
                >
    <TextBlock Text="Home" Foreground="White"/>
</Button>

<Button x:Name="userSetingsButton" 
                Height="55"
                Width="75"
                Background="#FF334166"
                Foreground="{x:Null}"
                FontSize="20"
                BorderBrush="{x:Null}"
                FontFamily="Tahoma"
                Canvas.Top="{Binding UserSettingsButtonViewModel.CanvasTop}"
                Canvas.Left="{Binding UserSettingsButtonViewModel.CanvasLeft}"
                >
    <TextBlock Text="User set" Foreground="White"/>
</Button>

Finally, you need to set the properties of the view model instance(s) that you actually bind to in the code-behind of the window (where you should also set the DataContext of the window):

public partial class MainWindow : Window
{
    private readonly MainWindowVieModel _viewModel = new MainWindowVieModel();

    public MainWindow()
    {
        InitializeComponent();
        DataContext = _viewModel;
    }

    private void changeButton_Click(object sender, RoutedEventArgs e)
    {
        bool mode = !(bool)Settings.Default["mode7"];
        Settings.Default["mode7"] = mode;
        Settings.Default.Save();

        _viewModel.HomeButtonViewModel.CanvasTop = mode ? 1 : 0;

        _viewModel.UserSettingsButtonViewModel.CanvasTop = mode ? 102 : double.NaN;
        _viewModel.UserSettingsButtonViewModel.CanvasLeft = mode ? -1 : double.NaN;
    }
}

huangapple
  • 本文由 发表于 2023年6月8日 21:39:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76432458.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定