2009-08-15 33 views
6

Tôi có một lớp tĩnh có chứa một RoutedUICommand mà tôi muốn sử dụng trong ràng buộc.Ràng buộc với một RoutedUICommand không có trong codebehind

public static class CommandLibrary 
{ 
    public static ProjectViewModel Project { get; set; } 

    public static RoutedUICommand AddPage { get; private set; } 

    static CommandLibrary() 
    { 
     AddPage = new RoutedUICommand("AddPage", "AddPage", typeof(CommandLibrary)); 

    } 

    public static void AddPage_Executed(object sender, ExecutedRoutedEventArgs args) 
    { 
     Project.AddPage(); 
    } 

    public static void AddPage_CanExecute(object sender, CanExecuteRoutedEventArgs args) 
    { 
     // We need a project before we can add pages. 
     if (Project != null) 
     { 
      args.CanExecute = true; 
     } 
     else 
     { 
      // Did not find project, turning Add Page off. 
      args.CanExecute = false; 
     } 
    } 
} 

Khi tôi cố gắng để tạo ra một CommandBinding cho lệnh AddPage này, VS ném một cơn giận, phàn nàn rằng nó không thể tìm thấy AddPage_CanExecute trong Window1 ... Mà làm cho không có ý nghĩa xem xét rằng tất cả các ví dụ tôi đã nhìn thấy chỉ ra XAML này nên được tốt xem xét đoạn code tôi có tại chỗ:

<Window x:Class="MyProject.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:MyProject"> 
    <Menu> 
     <Menu.CommandBindings> 
      <CommandBinding Command="local:CommandLibrary.AddPage" 
          Executed="AddPage_Executed" CanExecute="AddPage_CanExecute" /> 
     </Menu.CommandBindings> 
     <MenuItem Header="_Page"> 
      <MenuItem Header="_New" Command="local:CommandLibrary.AddPage" /> 
     </MenuItem> 
    </Menu> 
</Window> 

tôi cũng đã cố gắng không bao gồm phần Menu.CommandBindings và chỉ đơn giản là sử dụng này (theo this question mà gợi ý này, nhưng không phải là cụ thể):

<MenuItem Header="_New" Command="{x:Static local:CommandLibrary.AddPage}" /> 

Điều đó tạo ra luồng lỗi nhưng mục menu mà nó tạo ra luôn bị tắt! CanExecute dường như không bao giờ được gọi. Tôi giả định ràng buộc là không trong trường hợp này, là tốt, mặc dù lặng lẽ hơn.

Tại sao VS ghét lệnh của tôi và từ chối tìm đúng địa điểm để tìm phương thức Thực thi và CanExecute? Tôi đã xem một số ví dụ (trong Pro WPF bởi Matthew McDonald và trên một số hướng dẫn trực tuyến tùy chỉnh) đã thực hiện việc này khi tôi đang thực hiện.

Trả lời

11

A CommandBinding giống như bất kỳ phần tử nào khác trong cây thị giác của bạn. Bất kỳ sự kiện nào được chỉ định trên nó sẽ được xử lý bởi gốc của cây thị giác của bạn (Window trong trường hợp này). Điều đó có nghĩa là nếu bạn di chuyển AddPage_ExecutedAddPage_CanExecute vào mã cửa sổ của bạn, nó sẽ hoạt động. Điều này cho phép bạn sử dụng cùng một lệnh trong nhiều thành phần giao diện người dùng nhưng có các trình xử lý khác nhau.

Tôi thấy, tuy nhiên, lệnh của bạn thực hiện một số logic đối với mô hình chế độ xem của bạn. Để tiết kiệm thời gian và thất vọng cho bạn, hãy hiểu rằng các lệnh được định tuyến là giải pháp sai ở đây. Thay vào đó, đóng gói lệnh của bạn trong một cái gì đó xem mô hình của bạn như thế này:

public class ProjectViewModel 
{ 
    private readonly ICollection<PageViewModel> _pages; 
    private readonly ICommand _addPageCommand; 

    public ProjectViewModel() 
    { 
     _pages = new ObservableCollection<PageViewModel>(); 
     _addPageCommand = new DelegateCommand(AddPage); 
    } 

    public ICommand AddPageCommand 
    { 
     get { return _addPageCommand; } 
    } 

    private void AddPage(object state) 
    { 
     _pages.Add(new PageViewModel()); 
    } 
} 

Một DelegateCommand là một thực hiện ICommand mà gọi các đại biểu để thực hiện và truy vấn lệnh. Điều đó có nghĩa là logic lệnh được bao bọc trong lệnh và bạn không cần CommandBinding để cung cấp các trình xử lý (bạn không cần một số CommandBinding). Vì vậy, quan điểm của bạn chỉ cần liên kết với VM của bạn như sau:

<MenuItem Header="_New" Command="{Binding AddPageCommand}"/> 

tôi đề nghị bạn đọc qua loạt bài này của bài viết để cung cấp cho bạn bối cảnh hơn:

+0

Câu trả lời hay. Đã cho tôi những gì tôi cần. Tôi đã đọc qua một số hướng dẫn MVVM và thấy loại sử dụng lệnh này trước đây, nhưng không thể nhớ làm thế nào để làm điều đó vì vậy tôi viện đến các giải pháp tôi tìm thấy trong sách của tôi và thông qua tìm kiếm. Cảm ơn bạn đã giúp đỡ. – evizaer

+0

Đẹp. Tôi đã đập đầu của tôi trên này ... học wpf + mvvm không phải là thẳng về phía trước như tôi muốn. RoutedUICommands nơi quá phức tạp cho những gì tôi dự định và tôi biết rằng cần phải có một cách đơn giản hơn. @Kent, Cảm ơn các ví dụ và blog của bạn. –

Các vấn đề liên quan