UWP的MVVM模式教程,但它不会绑定命令为什么?

时间:2017-04-01 08:19:34

标签: c# xaml mvvm uwp uwp-xaml

确定。我正在按照一个教程来掌握MVVM模式到我的应用程序。

我已经很好地遵循了教程,我完成了部分命令,当我尝试将命令应用于按钮时,它似乎根本无法工作,我的按钮永远不会禁用。 我已经看过其他MVVM源代码,我的代码似乎没问题,除了我在互联网上发现这个教程是为了WPF,但它也适用于UWP Windows 10应用程序。

所以我会粘贴我的类和Xaml视图。

这是我的模特:

using System.ComponentModel;

namespace MVVMDemo.Model
{
public class Student : INotifyPropertyChanged
{
    private string firstName;
    private string lastName;

    public string FirstName
    {
        get
        {
            return firstName;
        }

        set
        {
            if (firstName != value)
            {
                firstName = value;
                RaisePropertyChanged("FirstName");
                RaisePropertyChanged("FullName");
            }
        }
    }

    public string LastName
    {
        get { return lastName; }

        set
        {
            if (lastName != value)
            {
                lastName = value;
                RaisePropertyChanged("LastName");
                RaisePropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return firstName + " " + lastName;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    private void RaisePropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }
}
}

我认为模型代码没有错误。 这是我的ViewModel:

using MVVMDemo.Model;
using System.Collections.ObjectModel;

namespace MVVMDemo.ViewModel
{
public class StudentViewModel
{
    /*Let’s add a property of MyICommand type in StudentView Model class. 
     * Now we need to construct an instance in the StudentViewModel. We will
     * use the overloaded constructor of MyICommand that takes two parameters.*/
    public MyICommand DeleteCommand { get; set; }

    /*Now add the implementation of OnDelete and CanDelete methods.*/
    public StudentViewModel()
    {
        LoadStudents();
        DeleteCommand = new MyICommand(OnDelete, CanDelete);
    }

    private bool CanDelete()
    {
        //if (SelectedStudent != null)
        //    return true;
        //return false;
        return SelectedStudent != null;
    }

    private void OnDelete()
    {
        Students.Remove(SelectedStudent);
    }

    /*We also need to add a new SelectedStudent so that the user 
     * can delete the Selected Item from ListBox.*/
    private Student _selectedStudent;

    public Student SelectedStudent
    {
        get
        {
            return _selectedStudent;
        }
        set
        {
            _selectedStudent = value;
            DeleteCommand.RaiseCanExecuteChanged();
        }
    }
    public ObservableCollection<Student> Students
    {
        get;
        set;
    }


    public void LoadStudents()
    {
        ObservableCollection<Student> students = new ObservableCollection<Student>();

        students.Add(new Student { FirstName = "Mark", LastName = "Allain" });
        students.Add(new Student { FirstName = "Allen", LastName = "Brown" });
        students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });

        Students = students;
    }
}
}

这是我的ViewModelLocator:

using MVVMDemo.ViewModel;

namespace MVVMDemo.VML
{
public class ViewModelLocator
{
private static StudentViewModel studentViewModel = new StudentViewModel();

    public static StudentViewModel StudentViewModel
    {
        get { return studentViewModel; }
    }
}
}

并且最后这是我的查看我的UserControl StudentView

<UserControl
    x:Class="MVVMDemo.Views.StudentView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MVVMDemo.Views"
    xmlns:vml="using:MVVMDemo.VML"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    DataContext="{Binding Source={StaticResource mainViewModelLocator}, Path=StudentViewModel}"
    d:DesignHeight="300"
    d:DesignWidth="400">  

<!--We will apply MVVM Using ItemTemplates-->
<UserControl.Resources>
    <DataTemplate x:Key = "studentsTemplate">

        <StackPanel Orientation = "Horizontal">
            <TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}" 
        Width = "100" Margin = "3 5 3 5"/>

            <TextBox Text = "{Binding Path = LastName, Mode = TwoWay}" 
        Width = "100" Margin = "0 5 3 5"/>

            <TextBlock Text = "{Binding Path = FullName, Mode = OneWay}" 
        Margin = "0 5 3 5"/>
        </StackPanel>

    </DataTemplate>
</UserControl.Resources>

<Grid>
    <StackPanel Orientation="Horizontal">
        <!--In StudentView.xaml, we need to add SelectedItem property in a ListBox
        which will bind to the SelectStudent property.-->
        <ListView ItemsSource="{Binding Students}" 
                  ItemTemplate="{StaticResource studentsTemplate}"
                  SelectedItem="{Binding SelectedStudent}"/>

        <Button Content = "Delete"  
                Command="{Binding DeleteCommand}"
                HorizontalAlignment = "Left" 
                VerticalAlignment = "Top" 
                Width = "75"/>
    </StackPanel>        
</Grid>
</UserControl>

我在应用程序级别的app.xaml文件中应用了viewmodellocator:

<Application.Resources>
    <vml:ViewModelLocator x:Key="mainViewModelLocator"/>
</Application.Resources>

我在主页面上调用我的观点:

可以有人帮助我,我在VS2015和VS2017上运行此代码并且删除按钮永远不会启用它也不会删除列表视图或列表框中的行我尝试更改它们似乎没有任何东西与众不同。

我甚至没有使用在这里使用的relaycommand模式的命令实现。 我很感激你的帮助。

感谢!!!

2 个答案:

答案 0 :(得分:6)

编辑:(这不是答案,而是另一种方法)

您知道吗?您可以使用 {x:Bind} 将方法直接绑定到事件。您无需使用 ICommand

XAML

     <Button Grid.Row="4"
      x:Uid="Send"
      VerticalAlignment="Top"
      HorizontalAlignment="Left"
      MinWidth="80"
      Click="{x:Bind ViewModel.SendFeedback}"/>

背后的代码

    public async void SendFeedback()
    {
        // Code
    }

这种方式更容易:)

答案 1 :(得分:1)

您在设置器中缺少一行来引发属性更改通知

public Student SelectedStudent
{
    get
    {
        return _selectedStudent;
    }
    set
    {
        _selectedStudent = value;
        RaisePropertyChanged("SelectedStudent"); // your version of this notifier
        DeleteCommand.RaiseCanExecuteChanged();
    }
}

以上内容足以解决问题,但除此之外,您只需检查CanDelete中的私人支持字段:

return _selectedStudent != null;