gpt4 book ai didi

c# - DataItem=null on binding,找不到原因?

转载 作者:太空宇宙 更新时间:2023-11-03 10:36:23 26 4
gpt4 key购买 nike

我正在尝试重现 Sheridan's answer to this question 中的建议在将 WPF 与 MVVM 模式结合使用时浏览我的 View 。不幸的是,我这样做时遇到了绑定(bind)错误。这是确切的错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='JollyFinance.ViewModels.MainViewModel', AncestorLevel='1''. BindingExpression:Path=DataContext.DisplayTest; DataItem=null; target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')

当我查看 LoginView.xaml 中的 xaml 代码时,我注意到 Visual Studio 告诉我它无法在 MainViewModel 类型的上下文中找到 DataContext.DisplayText。我尝试删除 DataContext. 并只保留 DisplayText,但无济于事。

除非 Sheridan 的回答有误,否则我肯定遗漏了一些东西。我应该怎么做才能让它发挥作用?

主窗口.xaml:

<Window x:Class="JollyFinance.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:JollyFinance.ViewModels"
xmlns:views="clr-namespace:JollyFinance.Views"
Title="JollyFinance!" Height="720" Width="1280">

<Window.Resources>
<!-- Different pages -->
<DataTemplate DataType="{x:Type vm:LoginViewModel}">
<views:LoginView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:TestViewModel}">
<views:Test/>
</DataTemplate>
</Window.Resources>

<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>

<Grid>
<ContentControl Content="{Binding CurrentViewModel}"/>
</Grid>
</Window>

MainViewModel.cs:

public class MainViewModel : BindableObject
{
private ViewModelNavigationBase _currentViewModel;

public MainViewModel()
{
CurrentViewModel = new LoginViewModel();
}

public ICommand DisplayTest
{
get
{
// This is added just to see if the ICommand is actually called when I press the
// Create New User button
Window popup = new Window();
popup.ShowDialog();

// View model that doesn't contain anything for now
return new RelayCommand(action => CurrentViewModel = new TestViewModel());
}
}

public ViewModelNavigationBase CurrentViewModel
{
get { return _currentViewModel; }
set
{
if (_currentViewModel != value)
{
_currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
}
}

登录 View .xaml:

<UserControl x:Class="JollyFinance.Views.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:JollyFinance.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">

<UserControl.DataContext>
<vm:LoginViewModel/>
</UserControl.DataContext>

<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<TextBlock Text="Username: " Grid.Column="1" Grid.Row="1" Margin="5"/>
<TextBox Text="{Binding Path=Username}" Grid.Column="2" Grid.Row="1" Grid.ColumnSpan="2" Margin="5"/>

<TextBlock Text="Password: " Grid.Column="1" Grid.Row="2" Margin="5"/>
<PasswordBox x:Name="PasswordBox" PasswordChar="*" Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="2" Margin="5"/>

<Button Content="Log In" Grid.Column="2" Grid.Row="3" Margin="5" Padding="5" Command="{Binding LoginCommand}"/>
<Button Content="Create new user" Grid.Column="3" Grid.Row="3" Margin="5" Padding="5"
Command="{Binding DataContext.DisplayTest, RelativeSource={RelativeSource AncestorType={x:Type vm:MainViewModel}},
Mode=OneWay}"/>

</Grid>

</UserControl>

登录 View 模型.cs:

public class LoginViewModel : ViewModelNavigationBase
{
public LoginViewModel()
{
LoginCommand = new RelayCommand(Login);
}

private void Login(object param)
{
// Just there to make sure the ICommand is actually called when I press the
// Login button
Window popup = new Window();
popup.ShowDialog();
}

public String Username { get; set; }

public String Password { get; set; }

public ICommand LoginCommand { get; set; }
}

ViewModelNavigationBase 只是一个实现了 INotifyPropertyChanged 接口(interface)的类,而 Test.xaml 和 TestViewModel.cs 只是一个用于测试目的的虚拟 View 模型/ View 。

最佳答案

在我的回答中,我声明您应该在 App.xaml 中声明您的 View 模型 DataTemplate,以便每个 View 都可以访问它们。将它们放在 MainWindow 类中是您的第一个问题。

另一个错误是您的 ICommandBinding Path。如果您想从设置为 Window.DataContext 的 View 模型访问某些内容,那么您应该使用RelativeSource Binding。试试这个:

<Button Content="Create new user" Grid.Column="3" Grid.Row="3" Margin="5" Padding="5" 
Command="{Binding DataContext.DisplayTest}, Mode=OneWay}" />

还要记住,无论出于何种原因,您选择让您的 MainViewModel 类扩展 ViewModelNavigationBase 类...这也可能导致你的问题。

无论如何,如果这不能解决您的问题,请告诉我。此外,如果您想在 Stack Overflow 上随时通知用户,只需在他们的名字前面放一个 @ 符号,他们就会收到通知。如果你这样做的话,你可以直接问我这个问题。

关于c# - DataItem=null on binding,找不到原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27613963/

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