2016-03-03 3 views
0

Попытка изучить WPF, и я прочитал/протестировал его с помощью учебника.Знакомство с шаблоном проектирования iCommand

Это мой сценарий:

МОФ C# приложение. В моем главном окне есть UserControl. В этом UserControl есть 4 кнопки. Мое намерение - связать каждое событие команды (щелчка) с каждой кнопкой. Но вместо привязки каждой кнопки к своему классу я хочу связать каждое командное событие этих 4 кнопок с 1 классом. Итак, я хотел передать параметр методам CanExecute и Execute, и я/пытаюсь передать enum этим методам. так .. то, что я получил до сих пор это:

public event EventHandler CanExecuteChanged 
{ 
    add { CommandManager.RequerySuggested += value; } 
    remove { CommandManager.RequerySuggested -= value; } 
} 

public bool CanExecute(object parameter) 
{ 
    var commandChosen= parameter as TopMenuCommands; 
    return true; 
} 

public void Execute(object parameter) 
{ 
    var buttonChosen = parameter as MenuCommandObject; 
    evMenuChange(buttonChosen); 
} 

public enum enTopMenuCommands 
{ 
    Button1 = 0, 
    Button1 = 1, 
    Button1 = 2, 
    Button1 = 3 
} 

Но как я могу связать это к моему главному окну?

Я признаю, что, возможно, я все это делаю неправильно, но я все еще участвую.

благодарит

ответ

2

Моей ICommand реализации занимает Action<object> в конструкторе. Метод Execute только что вызвал Action.

Таким образом, логика для каждой команды передается из того места, где она создана. Реализация

ICommand:

public class SimpleCommand : ICommand 
    { 
     public event EventHandler CanExecuteChanged; 

     private Action<object> _execute; 
     private Func<bool> _canExecute; 

     public SimpleCommand(Action<object> execute) : this(execute, null) { } 

     public SimpleCommand(Action<object> execute, Func<bool> canExecute) 
     { 
      _execute = execute; 
      _canExecute = canExecute; 
     } 

     public bool CanExecute(object param) 
     { 
      if (_canExecute != null) 
      { 
       return _canExecute.Invoke(); 
      } 
      else 
      { 
       return true; 
      } 
     } 

     public void Execute(object param) 
     { 
      _execute.Invoke(param); 
     } 

     protected void OnCanExecuteChanged() 
     { 
      CanExecuteChanged?.Invoke(this,EventArgs.Empty); 
     } 

     #region Common Commands 
     private static SimpleCommand _notImplementedCommand; 
     public static ICommand NotImplementedCommand 
     { 
      get 
      { 
       if (_notImplementedCommand == null) 
       { 
        _notImplementedCommand = new SimpleCommand(o => { throw new NotImplementedException(); }); 
       } 
       return _notImplementedCommand; 
      } 
     } 
     #endregion 
    } 

Пример использования:

using System; 
using System.Data.Entity; 
using System.Linq; 
using System.Runtime.CompilerServices; 
using System.Windows.Input; 
using SqlMetaQuery.Model; 
using SqlMetaQuery.ViewModels.ScriptList; 
using SqlMetaQuery.Windows.EditQuery; 
using WpfLib; 

namespace SqlMetaQuery.Windows.Main 
{ 
    class MainWindowVm : WpfLib.ViewModel 
    { 
     public MainWindowVm() 
     { 
      if (!IsInDesignMode) 
      { 
       using (Context db = new Context()) 
       { 
        ScriptTree = new ScriptTreeVm(db.Tags 
         .Include(t => t.Scripts) 
         .OrderBy(t => t.Name)); 

        CurrentUser = db.Users.Where(u => u.UserName == "Admin").AsNoTracking().FirstOrDefault(); 
        MiscTag = db.Tags.Where(t => t.Name == "Misc").AsNoTracking().FirstOrDefault(); 

       } 
      } 
     } 

     public ScriptTreeVm ScriptTree { get; } 

     public Model.User CurrentUser { get; } 

     private Model.Tag MiscTag { get; } 

     private void SaveScript(Model.Script script) 
     { 
      using (var context = new Model.Context()) 
      { 
       context.Scripts.Add(script); 
       context.SaveChanges(); 
      } 
     } 

     #region Commands 

     private ICommand _exitCommand; 
     public ICommand ExitCommand 
     { 
      get 
      { 
       if (_exitCommand == null) 
       { 
        _exitCommand = new SimpleCommand((arg) => WindowManager.CloseAll()); 
       } 
       return _exitCommand; 
      } 
     } 

     private ICommand _newScriptCommand; 
     public ICommand NewScriptCommand 
     { 
      get 
      { 
       if (_newScriptCommand == null) 
       { 
        _newScriptCommand = new SimpleCommand((arg) => 
        { 
         var script = new Model.Script() 
         { 
          Title = "New Script", 
          Description = "A new script.", 
          Body = "" 
         }; 
         script.Tags.Add(MiscTag); 
         var vm = new EditQueryWindowVm(script); 
         var result = WindowManager.DisplayDialogFor(vm); 

         // if (result.HasValue && result.Value) 
         //{ 
         script.VersionCode = Guid.NewGuid(); 
         script.CreatedBy = CurrentUser; 
         script.CreatedDate = DateTime.Now.ToUniversalTime(); 
         SaveScript(script); 
         //} 
        }); 
       } 
       return _newScriptCommand; 
      } 
     } 


     #endregion 
    } 
} 

XAML:

<Window x:Class="SqlMetaQuery.Windows.Main.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:controls="clr-namespace:SqlMetaQuery.Controls" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:SqlMetaQuery.Windows.Main" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     Title="MainWindow" 
     Width="800" 
     Height="600" 
     d:DataContext="{d:DesignInstance Type=local:MainWindowVm}" 
     mc:Ignorable="d"> 
    <DockPanel> 
     <Menu DockPanel.Dock="Top"> 
      <MenuItem Header="File"> 
       <MenuItem Command="{Binding Path=NewScriptCommand}" Header="New Script..." /> 
       <Separator /> 
       <MenuItem Command="{Binding Path=ExitCommand}" Header="Exit" /> 
      </MenuItem> 
     </Menu> 
     <Grid Margin="8"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="250" /> 
       <ColumnDefinition Width="Auto" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 
      <controls:ScriptTree Grid.Row="0" 
           Grid.Column="0" 
           DataContext="{Binding Path=ScriptTree}" /> 
      <GridSplitter Grid.Row="0" 
          Grid.Column="1" 
          Width="8" 
          VerticalAlignment="Stretch" 
          ResizeBehavior="PreviousAndNext" /> 
      <Grid Grid.Row="0" Grid.Column="2"> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="8" /> 
        <RowDefinition Height="*" /> 
       </Grid.RowDefinitions> 
       <Border Grid.Row="0" Style="{StaticResource BorderStandard}"> 
        <TextBlock Text="{Binding Path=ScriptTree.CurrentScript.Title}" /> 
       </Border> 
       <Border Grid.Row="3" Style="{StaticResource BorderStandard}"> 
        <TextBlock Text="{Binding Path=ScriptTree.CurrentScript.Body}" /> 
       </Border> 
      </Grid> 
     </Grid> 
    </DockPanel> 

</Window> 
+0

Привет, я знаю, что должен появиться довольно тусклый здесь б Вы можете дать мне пример в контексте того, что я пытаюсь сделать? Что такое лучшая практика? спасибо –

+0

Обновлено с примерами реализации и использования. –

+0

ничего себе! Благодарю. Позвольте мне переварить это и вернуться к вам. Хорошо, что вы сделали это –

Смежные вопросы