2009-11-06 16 views

cevap

3

Daha önce Button ve MenuItem nesnelerin Tag özelliğine ICommand nesneleri ekledim. (Örn Button, MenuItem)

0

ben bunu doğrudan sanmıyorum ama nasıl komutu çağırmak için düğmenin tıklama işleyicisi kullanmaya ne dersiniz? WPF kadar temiz değil ama yine de ayrılığını alıyorsun.

+0

Evet, aslında şu an şu an yapıyorum - bunu bağlayıcı bir şekilde yapmanın makul bir yolu olup olmadığını merak ediyorum. –

0

Ben WPF yanı sıra WinForms kullanabilirsiniz INotifyPropertyChanged uygulanması tavsiye ederim. Bazı ek bilgi için bir giriş ve here için bkz. here.

0

You denetimleri sınıflara deneyin hatta daha kolay bir yaşam için

private void button1_Click(object sender, EventArgs e) 
{ 
    ICommand command = ((Control)(sender)).Tag as ICommand; 

    if (command != null) 
    { 
     command.Execute(); 
    } 
} 

: Ben, örnek döküm ve eğer yapabilirsem çalıştırabilirsiniz eğer

Sonra ben sadece görmek WAF Windows Forms Adapter'u ilginç bulabilir. Windows Forms uygulamasında Model-View-ViewModel (MVVM) Kalıbının nasıl uygulanacağını gösterir. Adaptör uygulaması, Windows Forms'taki eksik Komutu desteği için bir çözüm sağlar. Aynı şeyin yapılabilir acaba ve Bu

denetimin etkin durumunu değiştirme (Application.Idle olayı üzerine) kayıtlı komutları sorgular ve veri bağlama kullanan basit bir CommandManager'da yazma sona erdi

13

Şu anda kullanıyorum kodu:

Ayrıca
public partial class Form1 : Form 
{ 
    private CommandManager commandManager; 

    public ICommand CommandA { get; set; } 
    public ICommand CommandB { get; set; } 

    public bool condition; 

    public Form1() 
    { 
     InitializeComponent(); 

     commandManager = new CommandManager(); 

     CommandA = new DelegateCommand("Command 1", OnTrue, OnExecute); 
     CommandB = new DelegateCommand("Command 2", OnFalse, OnExecute); 

     commandManager.Bind(CommandA, button1); 
     commandManager.Bind(CommandB, button2); 

     commandManager.Bind(CommandA, command1ToolStripMenuItem); 
     commandManager.Bind(CommandB, command2ToolStripMenuItem); 
    } 

    private bool OnFalse() 
    { 
     return !condition; 
    } 

    private bool OnTrue() 
    { 
     return condition; 
    } 

    private void OnExecute() 
    { 
     condition = !condition; 
    } 
} 

kod gerekirse, ben blogg:

public class CommandManager: Component 
{ 
    private IList<ICommand> Commands { get; set; } 
    private IList<ICommandBinder> Binders { get; set; } 

    public CommandManager() 
    { 
     Commands = new List<ICommand>(); 

     Binders = new List<ICommandBinder> 
         { 
          new ControlBinder(), 
          new MenuItemCommandBinder() 
         }; 

     Application.Idle += UpdateCommandState; 
    } 

    private void UpdateCommandState(object sender, EventArgs e) 
    { 
     Commands.Do(c => c.Enabled); 
    } 

    public CommandManager Bind(ICommand command, IComponent component) 
    { 
     if (!Commands.Contains(command)) 
      Commands.Add(command); 

     FindBinder(component).Bind(command, component); 
     return this; 
    } 

    protected ICommandBinder FindBinder(IComponent component) 
    { 
     var binder = GetBinderFor(component); 

     if (binder == null) 
      throw new Exception(string.Format("No binding found for component of type {0}", component.GetType().Name)); 

     return binder; 
    } 

    private ICommandBinder GetBinderFor(IComponent component) 
    { 
     var type = component.GetType(); 
     while (type != null) 
     { 
      var binder = Binders.FirstOrDefault(x => x.SourceType == type); 
      if (binder != null) 
       return binder; 

      type = type.BaseType; 
     } 

     return null; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
      Application.Idle -= UpdateCommandState; 

     base.Dispose(disposing); 
    } 
} 

public static class Extensions 
{ 
    public static void Do<T>(this IEnumerable<T> @this, Func<T, object> lambda) 
    { 
     foreach (var item in @this) 
      lambda(item); 
    } 
} 
public abstract class CommandBinder<T> : ICommandBinder where T: IComponent 
{ 
    public Type SourceType 
    { 
     get { return typeof (T); } 
    } 

    public void Bind(ICommand command, object source) 
    { 
     Bind(command, (T) source); 
    } 

    protected abstract void Bind(ICommand command, T source); 
} 

public class ControlBinder: CommandBinder<Control> 
{ 
    protected override void Bind(ICommand command, Control source) 
    { 
     source.DataBindings.Add("Enabled", command, "Enabled"); 
     source.DataBindings.Add("Text", command, "Name"); 
     source.Click += (o, e) => command.Execute(); 
    } 
} 

public class MenuItemCommandBinder : CommandBinder<ToolStripItem> 
{ 
    protected override void Bind(ICommand command, ToolStripItem source) 
    { 
     source.Text = command.Name; 
     source.Enabled = command.Enabled; 
     source.Click += (o, e) => command.Execute(); 

     command.PropertyChanged += (o, e) => source.Enabled = command.Enabled; 
    } 
} 

ve bu nasıl kullanılacağını bir xmaple olduğunu edition here

+0

çözümünüz gayet iyi çalışıyor ve diyalog bileşenlerini çok daha kolay ve anlaşılabilir hale getiriyor :-). çok teşekkürler! – rhe1980

+0

iyi çalışıyor ve hoşunuza gitti! –

+0

Neden "DataSourceUpdateMode", "DataBindings.Add (..)" yöntemini kullanarak 'Application.Idle' olayı kullandığınızı açıklar mısınız? –

5

Bir komutun, ButtonBase'dan miras alınan herhangi bir sınıfa bağlanmasına izin veren bir genel komut bağlama sınıfı oluşturabilirsiniz.

public class CommandBinding<T> where T : ButtonBase 
{ 
    private T _invoker; 
    private ICommand _command; 

    public CommandBinding(T invoker, ICommand command) 
    { 
     _invoker = invoker; 
     _command = command; 

     _invoker.Enabled = _command.CanExecute(null); 
     _invoker.Click += delegate { _command.Execute(null); }; 
     _command.CanExecuteChanged += delegate { _invoker.Enabled = _command.CanExecute(null); }; 
    } 
} 

sonra aşağıdaki kodu kullanarak ayarlanabilir bağlama komut:

: öylesine doğal bir kaç uyarılar vardır size bir başlangıç ​​vermek benim uygulanması

CommandBinding<Button> cmdBinding = 
    new CommandBinding<Button>(btnCut, CutCommand); 

Bu sadece çıplak kemikleri

  • Örnek, WPF ICommand arabiriminin kullanılmasını varsayar; bu nedenle, komut deseninin kendi uygulamanızın olması durumunda değiştirilmeniz gerekebilir.
  • Gönderilen parametreler boş başvurular için kontrol edilmelidir.
  • Daha somut bir uygulama, bellek sızıntılarını önlemek için olay işleyicilerini kaldırma yöntemine sahip olmalıdır.

jenerik kısıt da Click olayı ve komutlar hemen her Kontrole bağlı anlamına gelir Enabled özellik sunar Control için değiştirilebilir.

1
button1.Click += (s, e) => new MyCommand().Execute(); 
0

Eğer tasarımcı kullanarak denetime komutu bağlamak istiyorsanız Windows Formları MVVM nasıl kullanılacağını göstermek nerede bu demo uygulamasını kontrol edin:

https://bitbucket.org/lbras/mvvmforms

sahip olduğunuz tek kod kod arkasında yazmak için görünüm modeli örneğinin oluşturulmasıdır.