【问题标题】:C# binding won't work in WPF when using navigation in MVVM Light在 MVVM Light 中使用导航时,C# 绑定在 WPF 中不起作用
【发布时间】:2017-03-12 10:50:00
【问题描述】:

我使用 MVVMLight 和 MahApps 创建平面 UI 应用程序 (WPF)。我正在尝试让导航正常工作。

一切似乎都很好,但是在主窗口上由 Frame 托管的我的页面上的数据绑定存在问题。我声明我想在登录视图中绑定 LoginViewModel,但是当我尝试单击一个按钮(连接到 viewmodel 中的 RelayCommand)时,什么也没有发生(我已经用调试器检查过)。

如何绑定页面到viewmodel的好方法?

MVVM Light Navigation

这是我的 Login.xaml(页面):

<Page x:Class="Project.View.Login"
      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:local="clr-namespace:Project"
      xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
      mc:Ignorable="d" 
      d:DesignHeight="480" d:DesignWidth="640"
      Title="Login"
      DataContext="{Binding LoginViewModel, Source={StaticResource Locator}}">

    <Grid>
        <Button Command="{Binding GoToVote}" Content="{Binding Path=ButtonText}" HorizontalAlignment="Left" Margin="224,220,0,0" VerticalAlignment="Top" Width="75"/>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="224,320,0,0" TextWrapping="Wrap" Text="{Binding Path=ButtonText, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Page>

MainWindow.xaml(窗口):

<Controls:MetroWindow x:Class="Project.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Project"
        mc:Ignorable="d"
        xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        DataContext="{Binding MainViewModel, Source={StaticResource Locator}}"
        Title="MainWindow" Height="480" Width="640">
    <Frame Source="View/Login.xaml" x:Name="MainFrame" NavigationUIVisibility="Hidden" />
</Controls:MetroWindow>

ViewModelLocator.cs:

using Project.Tools;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using System;

namespace Project.ViewModel
{
    /// <summary>
    /// This class contains static references to all the view models in the
    /// application and provides an entry point for the bindings.
    /// </summary>
    public class ViewModelLocator
    {
        /// <summary>
        /// Initializes a new instance of the ViewModelLocator class.
        /// </summary>
        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            ////if (ViewModelBase.IsInDesignModeStatic)
            ////{
            ////    // Create design time view services and models
            ////    SimpleIoc.Default.Register<IDataService, DesignDataService>();
            ////}
            ////else
            ////{
            ////    // Create run time view services and models
            ////    SimpleIoc.Default.Register<IDataService, DataService>();
            ////}

            SimpleIoc.Default.Register<MainViewModel>();
            SimpleIoc.Default.Register<LoginViewModel>();
            SimpleIoc.Default.Register<VoteViewModel>();

            var navigationService = new FrameNavigationService();
            navigationService.Configure("Login", new Uri("../View/Login.xaml", UriKind.Relative));
            navigationService.Configure("Vote", new Uri("../View/Vote.xaml", UriKind.Relative));

            SimpleIoc.Default.Register<IFrameNavigationService>(() => navigationService);
        }

        public MainViewModel MainViewModel
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }

        public LoginViewModel LoginViewModel
        {
            get
            {
                return ServiceLocator.Current.GetInstance<LoginViewModel>();
            }
        }

        public VoteViewModel VoteViewModel
        {
            get
            {
                return ServiceLocator.Current.GetInstance<VoteViewModel>();
            }
        }

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

LoginViewModel.cs:

using Project.Tools;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project.ViewModel
{
    public class LoginViewModel : ViewModelNavigationBase
    {
        private string _buttonText;

        public RelayCommand GoCommand { get; private set; }

        void GoToVote()
        {
            _navigationService.NavigateTo("Vote");
        }

        public LoginViewModel(IFrameNavigationService navigationService) : base(navigationService)
        {
            GoCommand = new RelayCommand(GoToVote);
        }

        public string ButtonText
        {
            get { return _buttonText; }
            set
            {
                _buttonText = value;
            }
        }
    }
}

【问题讨论】:

    标签: c# .net wpf xaml mvvm


    【解决方案1】:

    您是否尝试在第一个 &lt;Grid&gt; 上设置数据绑定?在根级别对象上设置它可能会导致问题,因为该属性可能是由承载页面/窗口的控件设置的。

    <Page x:Class="Project.View.Login"
          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:local="clr-namespace:Project"
          xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
          mc:Ignorable="d" 
          d:DesignHeight="480" d:DesignWidth="640"
          Title="Login">
    
        <Grid DataContext="{Binding LoginViewModel, Source={StaticResource Locator}}">
            <Button Command="{Binding GoToVote}" Content="{Binding Path=ButtonText}" HorizontalAlignment="Left" Margin="224,220,0,0" VerticalAlignment="Top" Width="75"/>
            <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="224,320,0,0" TextWrapping="Wrap" Text="{Binding Path=ButtonText, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
        </Grid>
    </Page>
    

    主窗口上的内容可能相同。

    (我猜你在App.xaml中声明了Locator。)

    【讨论】:

    • 它没有按预期工作。奇怪的事情发生了 - 当我点击按钮时,没有任何动作,只刷新按钮的内容(在输入文本框后应该刷新按钮的内容 - 但它不起作用)。
    • 你有窥探吗? snoopwpf.codeplex.com 这将告诉您数据上下文实际上是什么。一旦你知道你会更好地了解正在发生的事情。
    • (注意什么 snoop 正在嗅探!)
    • 有用的工具。谢谢。
    【解决方案2】:

    尝试改变)

    使用 GalaSoft.MvvmLight.Command; -> 使用 GalaSoft.MvvmLight.CommandWpf;

    【讨论】:

      【解决方案3】:

      好的,解决了。

      我犯了两个可怕的错误(我不知道怎么做的)。 第一的: 在我的课堂 ViewModelNavigationBase 中,我忘记了实现 ViewModelBase(它是带有导航对象的扩展)。

      第二 - 我将按钮命令绑定到功能,而不是属性(ICommand)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多