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

iyr7buue  于 2023-06-19  发布在  其他
关注(0)|答案(1)|浏览(103)

这是我的项目树:

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

主窗口上有三个按钮。

<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类:

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

但点击时什么也没发生。我知道我做错了什么,但我不知道是什么。
//我也想使用命令而不是单击,但让我们解决一个问题。

e0uiprwp

e0uiprwp1#

不清楚为什么有两个视图模型。
无论如何,您应该将窗口的DataContext设置为单个视图模型的示例。在这一次,你可以初始化子视图模型:

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

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

然后,您可以使用以下语法通过视图中的主视图模型/DataContext绑定到子视图模型:

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

最后,你需要在窗口的代码隐藏中设置你实际绑定到的视图模型示例的属性(你还应该设置窗口的DataContext):

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

相关问题