2014-04-26 7 views
6

इतना आसान लगता है? मेरे पास एक वृक्ष दृश्य है, और मुझे कुछ ऐसा करना है जब नोड्स में से एक का विस्तार किया जाए। मैं एमवीवीएम का उपयोग कर रहा हूं, ताकि 'कुछ' ViewModel में एक कमांड है।जब TreeViewItem का विस्तार किया जाता है तो कमांड को आमंत्रित करें

ठीक है, मुझे लगता है कि यह सब के बाद इतना आसान नहीं है। मैंने चारों ओर देखा है और कुछ चीजों की कोशिश की है। उदाहरण के लिए, MVVM लाइट के EventToCommand का उपयोग कर:

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="TreeViewItem.Expanded"> 
     <cmd:EventToCommand Command="{Binding Path=FolderNodeToggledCommand}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

इस कोड (पर this और this आधार पर) काम नहीं करता है (कुछ भी नहीं आग; आदेश ViewModel में ही है लेकिन इसी विधि निकाल दिया कभी नहीं है जब एक नोड है विस्तार)। मैंने cmd:EventToCommand को i:InvokeCommandAction के साथ बदलने की भी कोशिश की है और परिणाम समान हैं। दूसरे लिंक में 'समाधान' स्पष्ट रूप से ओवरकिल है और मैं टॉगलबटन को बदलना नहीं चाहता क्योंकि मैं WPF TreeView WinForms Style का उपयोग करना चाहता हूं जिसका अपना टॉगल बटन है। दूसरे लिंक में द्वितीयक उत्तर से पता चलता है कि मैं TreeView पर किसी ईवेंट का उपयोग करने का प्रयास कर रहा हूं जो अस्तित्व में नहीं है।

अन्य possible solution TreeViewItem की IsExpanded संपत्ति को बांधने के लिए हो सकता है। हालांकि मैं उन वस्तुओं को रखना चाहता हूं जिन्हें मैं DTOs के रूप में बाध्यकारी कर रहा हूं और दृश्यमान में कोई कार्रवाई नहीं कर रहा हूं, न कि वस्तुओं को बाध्य किया जा रहा है।

तो जब TreeViewItem का विस्तार किया जाता है तो ViewModel में कमांड का आह्वान करने के लिए क्या होगा?

+0

हां, हर तरह से कृपया एक उत्तर पोस्ट करें। मैंने प्रिज्म का उपयोग नहीं किया है, लेकिन मैं देखूंगा कि मैं इसे काम कर सकता हूं या नहीं। – Gigi

+0

ठीक है, मैं एक उत्तर पोस्ट करूंगा जो एक चरण-दर-चरण देता है, और हम देखेंगे कि यह किसी भी उपयोग का है या नहीं। –

+0

नोट: चूंकि आदेश किसी व्यवहार से जुड़ा हुआ है, इसलिए आपको घोषणा ' –

उत्तर

7

यह काम करने के लिए, आप एक संलग्न व्यवहार का उपयोग कर सकते हैं, और आप देखेंगे कि यह एक स्वच्छ एमवीवीएम रणनीति है।

एक WPF अनुप्रयोग बनाएं और इस Xaml जोड़ने ...

<Grid> 
    <TreeView> 
     <TreeView.Resources> 
      <Style TargetType="TreeViewItem"> 
       <Setter Property="bindTreeViewExpand:Behaviours.ExpandingBehaviour" Value="{Binding ExpandingCommand}"/> 
      </Style> 
     </TreeView.Resources> 
     <TreeViewItem Header="this" > 
      <TreeViewItem Header="1"/> 
      <TreeViewItem Header="2"><TreeViewItem Header="Nested"></TreeViewItem></TreeViewItem> 
      <TreeViewItem Header="2"/> 
      <TreeViewItem Header="2"/> 
      <TreeViewItem Header="2"/> 
     </TreeViewItem> 
     <TreeViewItem Header="that" > 
      <TreeViewItem Header="1"/> 
      <TreeViewItem Header="2"/> 
      <TreeViewItem Header="2"/> 
      <TreeViewItem Header="2"/> 
      <TreeViewItem Header="2"/> 
     </TreeViewItem>   
    </TreeView> 
</Grid> 

फिर इस तरह एक दृश्य मॉडल बनाने ...

public class ViewModel : INotifyPropertyChanged 
{ 
    public ICommand ExpandingCommand { get; set; } 
    public ViewModel() 
    { 
     ExpandingCommand = new RelayCommand(ExecuteExpandingCommand, CanExecuteExpandingCommand); 
    } 
    private void ExecuteExpandingCommand(object obj) 
    { 
     Console.WriteLine(@"Expanded"); 
    } 
    private bool CanExecuteExpandingCommand(object obj) 
    { 
     return true; 
    } 
    #region INotifyPropertyChanged Implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected virtual void OnPropertyChanged(string name) 
    { 
     var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null); 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
} 

मैं रिले कमान उपयोग करें, लेकिन आप उपयोग कर सकते हैं बदले में कमांड कमांड। रिले कमान के लिए स्रोत http://msdn.microsoft.com/en-us/magazine/dd419663.aspx पर

तो एक अलग वर्ग है कि इस तरह दिखता है ...

public static class Behaviours 
{ 
    #region ExpandingBehaviour (Attached DependencyProperty) 
    public static readonly DependencyProperty ExpandingBehaviourProperty = 
     DependencyProperty.RegisterAttached("ExpandingBehaviour", typeof(ICommand), typeof(Behaviours), 
      new PropertyMetadata(OnExpandingBehaviourChanged)); 
    public static void SetExpandingBehaviour(DependencyObject o, ICommand value) 
    { 
     o.SetValue(ExpandingBehaviourProperty, value); 
    } 
    public static ICommand GetExpandingBehaviour(DependencyObject o) 
    { 
     return (ICommand) o.GetValue(ExpandingBehaviourProperty); 
    } 
    private static void OnExpandingBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     TreeViewItem tvi = d as TreeViewItem; 
     if (tvi != null) 
     { 
      ICommand ic = e.NewValue as ICommand; 
      if (ic != null) 
      { 
       tvi.Expanded += (s, a) => 
       { 
        if (ic.CanExecute(a)) 
        { 
         ic.Execute(a); 

        } 
        a.Handled = true; 
       }; 
      } 
     } 
    } 
    #endregion 
} 

फिर अपने Xaml में इस वर्ग के नाम अंतरिक्ष आयात बनाने है ...

xmlns: bindTreeViewExpand = "clr-namespace: BindTreeViewExpand" (आपका नाम स्थान अलग होगा!)

Resharper यह आपके लिए करेगा, या आपको एक इंटेलिजेंस प्रॉम्प्ट देगा।

अंत में व्यू मॉडल को तार दें। इस तरह त्वरित और गंदी विधि का उपयोग करें ...

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 

फिर, के बाद नाम रिक्त स्थान हल कर रहे हैं और तारों सही है, तो यह काम शुरू कर देंगे। निष्पादन विधि में अपना डीबगर एंकर करें और देखें कि आपको रूटेड इवेंट तर्क मिलता है। आप किस पेड़ दृश्य आइटम का विस्तार किया गया था यह जानने के लिए आप इसका विश्लेषण कर सकते हैं।

इस समाधान में महत्वपूर्ण पहलू स्टाइल में निर्दिष्ट व्यवहार है! तो यह प्रत्येक TreeViewItem पर लागू होता है। या तो पीछे कोई कोड नहीं (व्यवहार के अलावा)।

ऊपर सूचीबद्ध व्यवहार घटना को संभालने के रूप में चिह्नित करता है। आप जिस व्यवहार के बाद हैं उसके आधार पर आप इसे बदलना चाहेंगे।

+1

मैंने कोशिश की और यह बहुत अच्छी तरह से काम करता है। माना जाता है कि यह कुछ ऐसा करने के लिए काफी प्रयास है जो इतना आसान होना चाहिए, लेकिन यह काम करता है और यह अच्छा करता है। – Gigi

+0

बस गेटर –

+1

इनलाइन करने के लिए याद रखें यह ठीक काम करता है! इस समाधान – peter70

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