通过绑定更改源Uri时,WPF帧内容不会更新

时间:2014-12-05 04:00:54

标签: c# wpf mvvm data-binding visual-studio-2013

我已经在这个问题上工作了几天,但似乎无法找到适用于我的应用程序的任何内容。

我的问题是我正在尝试使用包含按钮的用户控件来绑定更改帧的源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"/>

按钮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));
            }
        }
    }
}

任何&amp;所有人都很感激,即使它没有完全解决我的问题,任何有助于我更接近解决方案的事情都是好的!

提前致谢

2 个答案:

答案 0 :(得分:0)

而不是这样做

_currentPage = //some value;

这样做:

CurrentPage = //some value

更改属性而不是后备字段时将引发事件。

修改

还有一个建议是创建一个命令类,因为所有命令都是将字符串值设置为属性。您可以使用CommandParameter获取按钮名称。基于此设置Uri

答案 1 :(得分:0)

有一个类似的问题,有一个主窗口,其中有一个框架,当我打开一个openfiledialog并关闭它时,即使我调用了PropertyChanged(),这个框架(其他一些框架)也没有更新绑定的Property具有正确的值。对我来说,唯一的解决方案是删除绑定并使用NavigationService处理Content。如果您需要此属性,您可以使用其他方法来执行以下操作:

    private Page _dataExplorerContent;
    public Page DataExplorerContent
    {
        get { return _dataExplorerContent; }
        set
        {
            if(value != null)
            {
                contentFrame.Navigate(value)
                SetField(ref _dataExplorerContent, value);
            }
        }
    }