2012-11-26 11 views
14

तो मेरे पास एक सरल सेटअप है, इसकी पॉपुलटिंग घटना के साथ एक स्वत: पूर्ण बॉक्स है जिसे मैं एक कमांड से जोड़ना चाहता हूं। मैं का उपयोगट्रिगर्स का उपयोग करके कमांड को इवेंट तर्क कैसे पास कर सकता हूं?

clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity 

(वहाँ ऐसा करने के लिए एक बेहतर नाम स्थान है?)

यह एक बड़ी बात यह बाध्य करने के लिए नहीं है, बड़ी बात बाध्य आदेश है कि PopulatingEventArgs तर्क पारित करने के लिए है।

तो मैं इसे विशेष रूप से PRISM के सर्वोत्तम प्रथाओं और सामान्य रूप से एमवीवीएम के अनुसार कैसे कर सकता हूं?

+0

प्रश्न के शीर्षक में टैग न डालें। अच्छे शीर्षक लिखने पर [यह लिंक] देखें (http://meta.stackexchange.com/questions/10647/how-do-i-write-a-good-title); –

उत्तर

24

कोई अंतर्निहित तरीका तो यहाँ है, है कि कैसे मैं यह कर:

<Button Content="I am a button"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseEnter"> 
      <i:InvokeCommandAction Command="{Binding CommandWithNoArgs}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

हम EventArgsMouseEnter उपयोग नहीं कर सकते:

क्लासिक इंटरेक्शन ट्रिगर इस तरह प्रयोग किया जाता है बाध्यकारी के माध्यम से घटना, तो हम उस टुकड़े को संशोधित करने जा रहे हैं जो इसे दूर करता है।
जैसा होता है, वह टुकड़ा InvokeCommandAction है।

"तो हम बस इसे सबक्लास करने जा रहे हैं और एक सुविधाजनक विधि को ओवरराइड कर रहे हैं जो हमारे साथ इंतजार कर रहा था" जो मुझे लिखना पसंद था। लेकिन कक्षा सील कर दी गई है।

तो हम अपनी मूल उपवर्ग करने के लिए जा रहे हैं (सार) वर्ग: TriggerAction<DependencyObject>

सबसे बुनियादी दिया गया है:

public class InteractiveCommand : TriggerAction<DependencyObject> 
{ 
    protected override void Invoke(object parameter) 
    { 
    } 
} 

और वह parameter अपने EventArgs है!
लेकिन पकड़ो, यह इतना आसान नहीं है, हमें नियमित InvokeCommandAction के व्यवहार को पुन: पेश करना होगा।
परावर्तक के माध्यम से, मैंने इसे संकुचित कर दिया (लेकिन आप आधिकारिक स्रोत को देख सकते हैं, मैं सिर्फ आलसी हूं)।

हम CommandParameter निर्भरता संपत्ति के बारे में परवाह नहीं करेंगे, हम यह मानने जा रहे हैं कि यदि आप InvokeCommandAction के बजाय इसका उपयोग करते हैं, तो आप वास्तव में EventArgs हर बार चाहते हैं।

यहाँ पूर्ण वर्ग चला जाता है (WPF केवल, Silverlight के लिए संपादित करें देखें):

public class InteractiveCommand : TriggerAction<DependencyObject> 
{ 
    protected override void Invoke(object parameter) 
    { 
     if (base.AssociatedObject != null) 
     { 
      ICommand command = this.ResolveCommand(); 
      if ((command != null) && command.CanExecute(parameter)) 
      { 
       command.Execute(parameter); 
      } 
     } 
    } 

    private ICommand ResolveCommand() 
    { 
     ICommand command = null; 
     if (this.Command != null) 
     { 
      return this.Command; 
     } 
     if (base.AssociatedObject != null) 
     { 
      foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
      { 
       if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal)) 
       { 
        command = (ICommand)info.GetValue(base.AssociatedObject, null); 
       } 
      } 
     } 
     return command; 
    } 

    private string commandName; 
    public string CommandName 
    { 
     get 
     { 
      base.ReadPreamble(); 
      return this.commandName; 
     } 
     set 
     { 
      if (this.CommandName != value) 
      { 
       base.WritePreamble(); 
       this.commandName = value; 
       base.WritePostscript(); 
      } 
     } 
    } 

    #region Command 
    public ICommand Command 
    { 
     get { return (ICommand)GetValue(CommandProperty); } 
     set { SetValue(CommandProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty CommandProperty = 
     DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null)); 
    #endregion 
} 

किसी भी कोड आप इंटरनेट, से लाने के साथ होता है मैं अत्यधिक पूरी कक्षा के माध्यम से पढ़ने, और समझने की कोशिश कर recommand यह क्या करता है। इसे अपने ऐप में न फेंकें।

अब हम कर सकते हैं:

<Button Content="I am a button"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseEnter"> 
      <local:InteractiveCommand Command="{Binding CommandWithEventArgs}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

और पीछे कोड:

#region CommandWithEventArgs 
DelegateCommand<MouseEventArgs> _CommandWithEventArgs; 
/// <summary> 
/// Exposes <see cref="CommandWithEventArgs(MouseEventArgs)"/>. 
/// </summary> 
public DelegateCommand<MouseEventArgs> CommandWithEventArgs 
{ 
    get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand<MouseEventArgs>(CommandWithEventArgs)); } 
} 
#endregion 
public void CommandWithEventArgs(MouseEventArgs param) 
{ 
} 

और वह एक चादर है;)

संपादित करें: Silverlight के लिए, इस कोड के बजाय का उपयोग करें:

public class InteractiveCommand : TriggerAction<DependencyObject> 
    { 
     protected override void Invoke(object parameter) 
     { 
      if (base.AssociatedObject != null) 
      { 
       ICommand command = Command; 
       if ((command != null) && command.CanExecute(parameter)) 
       { 
        command.Execute(parameter); 
       } 
      } 
     } 

     #region Command 
     public ICommand Command 
     { 
      get { return (ICommand)GetValue(CommandProperty); } 
      set { SetValue(CommandProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CommandProperty = 
      DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null)); 
     #endregion 
    } 

लेकिन कृपया ध्यान दें कि पूर्ण पूर्ण WPF संस्करण (प्रकारों की जांच नहीं करता है, जमे हुए तत्वों के साथ क्रैश हो सकता है) का उपयोग करने से कम सुरक्षित है।

+0

मुझे लगता है कि यह बहुत ही लचीला है बॉक्स, जो उन चीजों का समर्थन करने के लिए विभिन्न एक्सटेंशन लिखने की ओर जाता है जो हम सोचते हैं मूल हैं। –

+0

बस आपके कोड की कोशिश की, भले ही मुझे यह पता चला कि कोड स्वयं काम नहीं करता है। (क्या यह एक बेहतर जगह से प्रतिलिपि/पेस्ट है?) मूल रूप से कमांडनाम कभी असाइन नहीं किया जाता है और इस प्रकार हल हो जाता है कमांड वापस लौटाता है और पूरी चीज उस वजह से काम नहीं करती है। कुछ मामूली समस्याएं भी हैं जो आधार जैसी चीजें हैं। राइटपोस्टस्क्रिप्ट(); बेस क्लास में परिभाषित नहीं हैं, लेकिन यह महत्वपूर्ण नहीं है –

+0

ठीक है, कृपया काम करने के लिए सिद्ध होने वाले फ़्लोइंग स्निपेट के साथ अपना कोड संशोधित करें: http://pastie.org/5437478, http://pastie.org/5437483 धन्यवाद दोबारा और एक अच्छा दिन है! –

35

मैंने इंटरएक्टिव कमांड की कोशिश की और इससे मेरे लिए समस्याएं आईं। इसके बजाय मैंने माइक्रोसॉफ्ट के लिए एक संदर्भ निर्धारित किया। एक्सप्रेशन। इंटरैक्शन और

xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="AppointmentEditing"> 
     <ei:CallMethodAction MethodName="AppointmentEditing" TargetObject="{Binding}" /> 
    </i:EventTrigger> 
    <i:EventTrigger EventName="ShowDialog"> 
     <ei:CallMethodAction MethodName="ShowDialog" TargetObject="{Binding}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

... मेरे उपयोगकर्ता नियंत्रण में शामिल है।

फिर जनता के लिए मेरी ViewModel में ईवेंट हैंडलर्स रख दिया और सेट गुंजाइश:

public void ShowDialog(object sender, ShowDialogEventArgs e) { 

} 

public void AppointmentEditing(object sender, AppointmentEditingEventArgs e) { 

} 

अच्छी तरह से काम करते हुए अब तक।

+1

के साथ यह बहुत उपयोगी है। – rajibdotnet

+5

ग्रेट !! यह subclassing से बचें और आदेशों का उपयोग कोड-पीछे – isra60

+4

से कोडहैंडर्स के रूप में करने के लिए अनुमति दें, मेरे लिए यह स्वीकार्य उत्तर –

संबंधित मुद्दे

 संबंधित मुद्दे