gpt4 book ai didi

c# - WPF MVVM subview 模型属性不更新 View

转载 作者:太空宇宙 更新时间:2023-11-03 21:02:20 24 4
gpt4 key购买 nike

所以我有一个使用 MVVM 模式的 WPF 应用程序,它使用 MVVM Light 库。 对于 INotifyPropertyChanged,我使用的是目前运行良好的 Fody.Weavers 库。

我有一个带有 ContentControl 的 MainWindow.xaml,其 Content 属性绑定(bind)到其 View 模型上的一个属性以进行导航。这也很有效。

主窗口.xaml:

<ContentControl Content="{Binding SelectedViewModel}"></ContentControl>

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
// Note that Fody library handles INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public object SelectedViewModel { get; set; }

public MainViewModel()
{
SelectedViewModel = new HomeViewModel();
}

public RelayCommand<PasswordBox> AdminLoginCommand => new RelayCommand<PasswordBox>(AdminLogin);

private void AdminLogin(PasswordBox passwordBox)
{
// Login Logic...

// Does not work
SelectedViewModel = new HomeViewModel();

// Does not work either
if (SelectedViewModel is HomeViewModel)
{
((HomeViewModel)SelectedViewModel).CheckAccess();
}

// Does not work either
if (SelectedViewModel is HomeViewModel)
{
((HomeViewModel)SelectedViewModel).CanAccessTestButton = true;
}
}
}

但是,当我在 SelectedViewModel 上调用 CheckAccess 方法时,直接更改 MainViewModel 的 CanAccessTestButton 属性,或使用 MainViewModels AdminLogin 方法中的新 HomeViewModel 设置 SelectedViewModel,当我逐步执行代码时,它们会更新,但绑定(bind)不更新用户界面。我已经独立尝试过这些方法。

我认为从父 View 模型更改时,Home.xaml 没有获取该属性。当 HomeViewModel 的构造函数在第一次加载时被初始化时,它正确地绑定(bind)到 CanAccessTestButton 设置的任何内容,来自 MainViewModel 的任何其他调用似乎都不会更新 View 。

有趣的是,当我尝试使用绑定(bind)到 Home.xaml 中另一个按钮的 RelayCommand 从 HomeViewModel 中更改属性时,它工作正常。

我怎样才能让它从 parent 那里工作?

首页.xaml:

<Button Content="Test" IsEnabled="{Binding CanAccessTestButton}"/>

HomeViewModel.cs:

public class HomeViewModel : ViewModelBase
{
// Note that Fody library handles INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public bool CanAccessTestButton { get; set; }

public HomeViewModel()
{
OtherButtonCommand = new RelayCommand(OtherButtonClick);
CheckAccess();
}

public RelayCommand OtherButtonCommand { get; set; }
private void OtherButtonClick()
{
// WORKS!!!
CheckAccess()
}

public void CheckAccess()
{
CanAccessTestButton = AppContext.Instance.LoggedInUserHasAccess();
}
}

编辑:MVVM Light 有一个 ViewModelLocator.cs 类,您需要在其中声明每个 ViewModel:

public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<HomeViewModel>();
}

public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();

public HomeViewModel Home => ServiceLocator.Current.GetInstance<HomeViewModel>();

public static void Cleanup()
{
// TODO Clear the ViewModels
}
}

然后在每个 View 中,您引用要绑定(bind)到的 View 模型(为简洁起见简化了标记)

主窗口.xaml:

<Window DataContext="{Binding Main, Source={StaticResource Locator}}">

首页.xaml:

<UserControl DataContext="{Binding Home, Source={StaticResource Locator}}">

启动时,HomeViewModel 构造函数被调用两次,第一次是从 ViewModelLocator.cs 调用,然后是从 MainViewModel.cs 调用一次。也许 ViewModelLocator 引用了我在屏幕上看到的 View 。关于如何实现我希望实现的目标有什么想法吗?

最佳答案

I noticed the HomeViewModel constructor gets called once from ViewModelLocator, then again within MainViewModel when the Content binding is set

那是你的问题。您正在创建 View 模型的另一个实例并绑定(bind)到这个实例。

Home.xaml 中的 UserControl 中删除 DataContext 属性:

<UserControl DataContext="{Binding Home, Source={StaticResource Locator}}">

您想绑定(bind)到您自己创建的 HomeViewModel 实例,而不是 View 模型定位器为您创建的实例。所以你在这里不需要任何 View 模型定位器。

关于c# - WPF MVVM subview 模型属性不更新 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44281527/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com