属性更改时 WPF 绑定不起作用



这是我在这里的第一个问题,请理解。我在这个问题上花了好几个小时挖掘,但对我来说什么都不管用,也许有人会给我解释这个奇怪的(对我来说(问题?我用MVVM 在WPF中制作了我的应用程序

我在MainWindow.xaml中使用了usercontrol,它加载带有绑定的视图:

<UserControl Content="{Binding CurrentView}" />

MainWindow DataContext是MainViewModel,它派生自BaseViewModel,我在其中设置和获取CurrentView,并实现INotifyPropertyChanged。

第一个CurrentView是LoginViewModel-它正确地加载在MainViewModel的构造函数中并设置视图(UsercontrolLoginview.xaml(。我不明白为什么当我从这个加载的LoginViewModel更改CurrentView属性时(它肯定会更改-我检查了它,并引发了NotifyPropertyChanged(-我的视图没有更改-它仍然是LoginView,但应该是WelcomeView。但是,当我用MainViewModel中的相同代码更改相同的属性时,我的视图会正确更改。有人可以指出哪里有错误?是否不可能从MainViewModel外部更改CurrentView属性,即使它不是MainViemodel的一部分,而是另一个类或其他什么?我在这里缺少什么?

代码:

public class BaseViewModel : NotifyPropertyChanged 
{
private object? _currentView;
public object? CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged(nameof(CurrentView));
}
}
}
public class MainViewModel : BaseViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public WelcomeViewModel WelcomeViewModel { get; set; }
[..]
public ICommand LoginCommand { get; set; } //- this works 
public MainViewModel()
{
LoginViewModel = new();
WelcomeViewModel = new();
CurrentView = LoginViewModel;
// COMMANDS
LoginCommand = new RelayCommand(o => DoLogin(), o => CanLogin()); // this works
}
private bool CanLogin()
{
return true;
}
private void DoLogin()
{
CurrentView = WelcomeViewModel;
} 
}
public class LoginViewModel : BaseViewModel
{
[...]
public WelcomeViewModel WelcomeViewModel { get; set; }
// COMMANDS PROPERTIES
public ICommand LoginCommand { get; set; }
public LoginViewModel()
{
WelcomeViewModel = new();
LoginCommand = new RelayCommand(o => DoLogin(), o => CanLogin());
}
private bool CanLogin()
{
return true;
}
private void DoLogin()
{
MessageBox.Show("Login!");  // message box test showes
// here will be some authentication
CurrentView = WelcomeViewModel; // property CurrentView changes
// CurrentView = new MainViewModel().WelcomeViewModel; // this way also doesn't work
}
}

最后是来自UserControl LoginView.XAML的XAML(命令运行正常,属性CurrentView更改,但视图保持不变:

<Button
Width="200"
Height="50"
Margin="10"
Command="{Binding LoginCommand}"
Content="Login"
FontSize="18" />
<!--  Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, 
Path=DataContext.LoginCommand}" THIS WORKS! -->

App.xaml具有:

<DataTemplate DataType="{x:Type vievmodels:LoginViewModel}">
<viewscontents:LoginView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vievmodels:WelcomeViewModel}">
<viewscontents:WelcomeView/>
</DataTemplate>

问题是:如何设置DataContext。。。。这样做。

主视图模型:

public class MainViewModel : BaseInpc
{
#region CurrentContent
private object? _currentContent;
public object? CurrentContent { get => _currentContent; set => Set(ref _currentContent, value); }
private RelayCommand _setCurrentCommand;
public RelayCommand SetCurrentCommand => _setCurrentCommand
??= new RelayCommand(content => CurrentContent = content);
#endregion
public LoginViewModel LoginViewModel { get; } = new LoginViewModel();
public WelcomeViewModel WelcomeViewModel { get; } = new WelcomeViewModel();
public MainViewModel()
{
CurrentContent = WelcomeViewModel;
}
}
public class WelcomeViewModel: BaseInpc // Derived not from MainViewModel!
{
// Some Code
}
public class LoginViewModel: BaseInpc // Derived not from MainViewModel!
{
// Some Code
}

在应用程序资源中创建MainViewModel的实例:

<Application.Resources>
<local:MainViewModel x:Key="mainVM"/>
</Application.Resources>

在Windows XAML中:

<Window ------------
------------
DataContext="{DynamicResource mainVM}">
<Window.Resources>
<DataTemplate DataType="{x:Type local:LoginViewModel}">
<local:LoginViewUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type WelcomeViewModel}">
<local:WelcomeViewUserControl/>
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentContent}"/>

按钮切换CurrentContent:的示例

<Button Command="{Binding SetCurrentCommand, Source={StaticResource mainVM}}"
CommandParameter="{Binding LoginViewModel, Source={StaticResource mainVM}}"/>

BaseInpc和RelayCommand类。

您犯的错误是有两个CurrentView变量。一个在CCD_ 2中,另一个则在LoginViewModel中。这两个类都是从BaseViewModel派生的,但这并不意味着它们共享CurrentView的同一实例。两者都有一个CurrentView变量的新实例。意味着只有一个绑定到页面的DataContext

我看不到的是,你把哪个CurrentView分配给DataContext。所以我不能完全回答这个问题。

但是看起来你有一个窗口,里面有两个控件。要解决此问题,您应该创建一个仅包含CurrentView的第三视图模型。在使用UserControl的父级上使用此实例。并将其他ViewModels用于用户控件本身。

最新更新