首页 > 解决方案 > 无法从 ViewModel 中的事件处理程序折叠元素

问题描述

我有一个带有两个按钮的简单 XAML 页面。我正在尝试动态折叠已单击的按钮并显示另一个按钮,但似乎无法使其工作。

为简单起见,按钮可见性直接绑定到类Visibility中的属性TestPageViewModel。事件处理程序绑定到它的方法。

测试页.xaml

<Page
    x:Class="CollapseElementTest.TestPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CollapseElementTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" d:DesignWidth="500" d:DesignHeight="500">
    <StackPanel>
        <Button Background="Blue" 
                Click="{x:Bind TestPageViewModel.HideBlueButton}" 
                Visibility="{x:Bind TestPageViewModel.BlueButtonVisibility, Mode=OneWay}"></Button>
        <Button Background="Red" 
                Click="{x:Bind TestPageViewModel.HideRedButton}"
                Visibility="{x:Bind TestPageViewModel.RedButtonVisibility, Mode=OneWay}"></Button>
    </StackPanel>
</Page>

测试页.xaml.cs

using Windows.UI.Xaml.Controls;

namespace CollapseElementTest
{
    public sealed partial class TestPage : Page
    {
        public TestPageViewModel TestPageViewModel { get; set; }
        public TestPage()
        {
            this.InitializeComponent();
            TestPageViewModel = new TestPageViewModel();
        }
    }
}

TestPageViewModel属性在 UI 线程上更新。

TestPageViewModel.cs

using System;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.Xaml;

namespace CollapseElementTest
{
    public class TestPageViewModel
    {
        public Visibility BlueButtonVisibility { get; set; } = Visibility.Visible;

        public Visibility RedButtonVisibility { get; set; } = Visibility.Collapsed;

        public async void HideBlueButton()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                BlueButtonVisibility = Visibility.Collapsed;
                RedButtonVisibility = Visibility.Visible;
            });
        }

        public async void HideRedButton()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                BlueButtonVisibility = Visibility.Visible;
                RedButtonVisibility = Visibility.Collapsed;
            });
        }
    }
}

应用程序启动后,显示蓝色按钮,但单击按钮后没有任何变化。我究竟做错了什么?

标签: uwpuwp-xaml

解决方案


你错过了这个部分INotifyPropertyChanged。当你更改了一个属性时,你需要通知应用程序,说这里发生了变化,让应用程序做接下来的步骤。

我将您的 ViewModel 文件修改为以下内容,并且可以正常工作。请检查。

public class TestPageViewModel : INotifyPropertyChanged
    {
        private Visibility _BlueButtonVisibility;

        public Visibility BlueButtonVisibility
        {
            get { return _BlueButtonVisibility; }
            set { Set(ref _BlueButtonVisibility, value); }
        }
        private Visibility _RedButtonVisibility;

        public Visibility RedButtonVisibility
        {
            get { return _RedButtonVisibility; }
            set { Set(ref _RedButtonVisibility, value); }
        }

        public async void HideBlueButton()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                BlueButtonVisibility = Visibility.Collapsed;
                RedButtonVisibility = Visibility.Visible;

                
            });
        }

        public async void HideRedButton()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                BlueButtonVisibility = Visibility.Visible;
                RedButtonVisibility = Visibility.Collapsed;
            });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value))
            {
                return;
            }

            storage = value;
            OnPropertyChanged(propertyName);
        }

        protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

推荐阅读