【发布时间】:2014-12-05 04:00:54
【问题描述】:
我已经在这个问题上工作了几天,似乎找不到任何适合我的应用程序的东西。
我的问题是我正在尝试使用包含按钮的用户控件来绑定到更改框架的源 Uri 的命令(两者都显示在同一个窗口中)。当我单击一个按钮时,它正在更改 ViewModel 中的 Uri,但框架不会更改页面以反映这一点。我相信它要么由于其绑定方式而没有接受更改,要么有一些东西阻止它更改框架中显示的页面。
我使用的 MVVM 模式一直很棒,直到我不得不开始处理导航。任何帮助将不胜感激!
导航用户控件视图按钮:
<Button Name="BtnMainDash" Content="Main Dashboard" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="180" Command="{Binding MainDashboard}"/>
<Button Name="BtnAccount" Content="Account" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top" Width="180" Command="{Binding EditAccount}"/>
<Button Name="BtnProjects" Content="Projects" HorizontalAlignment="Left" Margin="10,70,0,0" VerticalAlignment="Top" Width="180" Command="{Binding ProjectScreen}"/>
主窗口框架:
<Frame x:Name="FmePages" Margin="200,30,-0.4,0.4"
Source="{Binding Path=CurrentPage, Mode=OneWay, UpdateSourceTrigger=PropertyChanged }"
NavigationUIVisibility="Hidden"/>
Button ICommands(除了每个调用不同的 Uri 更改命令外都一样):
using System;
using System.Windows.Input;
using ScrumManagementApplication.Pages.MainWindow.ViewModel;
namespace ScrumManagementApplication.Pages.MainWindow.Commands
{
class LoadEditAccount : ICommand
{
private readonly NavigationViewModel _navigationViewModel;
public LoadEditAccount(NavigationViewModel navigationViewModel)
{
_navigationViewModel = navigationViewModel;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _navigationViewModel.CommandsEnabled;
}
public void Execute(object parameter)
{
_navigationViewModel.LoadEditAccount();
}
}
}
视图模型:
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using ScrumManagementApplication.Pages.MainWindow.Commands;
using ScrumManagementApplication.SessionData;
using MessageBox = System.Windows.MessageBox;
namespace ScrumManagementApplication.Pages.MainWindow.ViewModel
{
public class NavigationViewModel : INotifyPropertyChanged, INotifyPropertyChanging
{
public bool CommandsEnabled = false;
public NavigationViewModel()
{
MainDashboard = new LoadMainDashboard(this);
EditAccount = new LoadEditAccount(this);
ProjectScreen = new LoadProjectScreen(this);
LogOut = new LoadLogOut(this);
CommandsEnabled = true;
LoadEditAccount();
}
#region ICommands
public ICommand MainDashboard { get; private set; }
public void LoadMainDashboard()
{
_currentPage = null;
_currentPage = new Uri("pack://application:,,,/Pages/MainWindow/View/MainDashboardView.xaml", UriKind.Absolute);
}
public ICommand EditAccount { get; private set; }
public void LoadEditAccount()
{
_currentPage = null;
_currentPage = new Uri("pack://application:,,,/Pages/EditUserDetailsPage/View/EditUserDetailsView.xaml", UriKind.Absolute);
}
public ICommand ProjectScreen { get; private set; }
public void LoadProjectScreen()
{
_currentPage = null;
_currentPage = new Uri("pack://application:,,,/Pages/ProjCreationPage/View/ProjectCreationPage.xaml", UriKind.Absolute);
}
public ICommand LogOut { get; private set; }
public void LoadLogOut()
{
var dialogResult = MessageBox.Show("Are you sure you want to log out?", "Log Out", MessageBoxButton.YesNo);
if (dialogResult == (MessageBoxResult) DialogResult.Yes)
{
App.Current.Shutdown();
}
}
#endregion // ICommands
#region MainFrame
private Uri _currentPage;
public Uri CurrentPage
{
get { return _currentPage; }
set
{
_currentPage = value;
OnPropertyChanged("CurrentPage");
}
}
#endregion // MainFrame
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion // INotifyPropertyChanged Members
public event PropertyChangingEventHandler PropertyChanging;
protected void OnPropertyChanging(String propertyName)
{
PropertyChangingEventHandler handler = PropertyChanging;
if (handler != null)
{
handler(this, new PropertyChangingEventArgs(propertyName));
}
}
}
}
感谢所有帮助,即使它不能完全解决我的问题,任何帮助我更接近解决方案的东西都是好的!
提前致谢
【问题讨论】:
-
您必须引发
PropertyChanged事件,以便绑定系统更新目标属性。您只是在更改支持字段。请改用您编写的自动引发PropertyChanged事件的属性设置器。 -
@mikez 嗨,迈克,感谢您的帮助。我想我可能已经盯着屏幕太久了,因为我不是 100% 你的意思,你能详细说明一下吗?谢谢!
-
以
LoadEditAccount为例,您正在更改_currentPage而没有引发CurrentPage的属性更改事件。您需要在此之后的某个时间致电OnPropertyChanged("CurrentPage")。你可以把它写成CurrentPage = new Uri(...);,它会调用你的setter并引发事件。 -
@mikez 我已经尝试了这两种方法,但它仍然没有更改框架中的页面,我在 MessageBoxes 中添加以确保 Uri 正在正确更新并且那里没有问题。无论出于何种原因,框架似乎都不想改变它的初始来源
标签: c# wpf mvvm data-binding visual-studio-2013