2012-11-16 25 views
9

में मैंने एक कार्यालय ऐड-इन बनाया है जिसमें एक WPF अनुप्रयोग का उदाहरण है। उपयोगकर्ता ऐड-इन पर बटन क्लिक करता है, मैं निम्न कार्य करके अलग खिड़कियों का शुभारंभ:किसी कार्यालय से WPF विंडो लॉन्च करना

MyViewModel viewModel = new MyViewModel(string infoFromOffice); 
MyWindow view = new MyWindow(); 
view.DataContext = viewModel; 

wpfApp.Run(view); 

wpfApp.Run() करने के लिए अपने कॉल करने से पहले दृश्य मॉडल के निर्माण में मैं बाद में वर्तमान SynchronizationContext साथ probelms मारा। उत्तर here बताता है क्यों। क्या कार्यालय एड-इन से WPF विंडो लॉन्च करने का कोई बेहतर तरीका है?

+1

, यह 'wpfApp कॉल करने के लिए किसी भी फर्क पड़ता है।चलाएं (नया MyWindow {DataContext = नया MyViewModel (infoFromOffice)}); ' – Jay

+0

सुझाव के लिए धन्यवाद, दुर्भाग्य से यह काम नहीं करता है। – Coder1095

उत्तर

1

जबकि आर्थर की जवाब क्यों समस्या हो रहा था इंगित मदद की, यह वास्तव में एक मेजबान आवेदन से एक दृश्य मॉडल के लिए डेटा भेजने का तरीका, जबकि अभी भी हो रही दृश्य मॉडल निर्माता कॉल के बाद हो सकता है का जवाब नहीं दिया App.Run() पर कॉल करें। मुझे बाद में एक बहुत ही सरल समाधान मिला है! रुचि रखने वाले किसी भी व्यक्ति के लिए।

App.xaml.cs में:

private string data; 

public App(string infoFromOffice) { 
    this.data = data; 
} 

protected override void OnStartup(StartupEventArgs e) { 
    base.OnStartup(e); 

    MyViewModel viewwModel = new MyViewModel(this.data); 
    MyWindow view = new MyWindow(); 
    view.Show(); 
} 

जब एप्लिकेशन को लॉन्च:

App application = new App(infoFromOffice); 
application.Run(); 

ध्यान दें कि स्टार्टअप यूआरआई जरूरत App.xaml में हटा दिया जाना चाहिए। यह बहुत ही सरल समाधान मुझे अपने ऐप को जानकारी पास करने की इजाजत देता है, लेकिन साथ ही दृश्य मॉडल को "गैर डब्लूपीएफ पर्यावरण" में बनाया जाना आवश्यक नहीं है और इसलिए डिस्पैचर आदि का उपयोग कर सकते हैं

2

मैंने कभी भी Office ऐड-इन नहीं बनाया है, लेकिन मैंने अन्य प्रकार के गैर-WPF अनुप्रयोगों (विंडोज फॉर्म, पुस्तकालयों को WPF दृश्यों से उत्पन्न करने के लिए पुस्तकालयों आदि) में WPF विंडो का उपयोग किया है। आप this question. में सुझाए गए दृष्टिकोण को आजमा सकते हैं। यह दिखाता है कि थ्रेड को कॉन्फ़िगर कैसे करें ताकि यह WPF ऐप चला सके। आप एक WPF अनुप्रयोग के उत्पन्न ऐप्लिकेशन के कोड ("App.gics") पर एक नज़र रखना है, तो ऐसा लगता है इसे इस तरह शुरू कर दिया गया है:

/// <summary> 
    /// Application Entry Point. 
    /// </summary> 
    [System.STAThreadAttribute()] 
    [System.Diagnostics.DebuggerNonUserCodeAttribute()] 
    public static void Main() { 
     WpfApplication1.App app = new WpfApplication1.App(); 
     app.InitializeComponent(); 
     app.Run(); 
    } 

मैं के साथ एक इकाई परीक्षण से किसी एप्लिकेशन की लॉन्चिंग की कोशिश की निम्नलिखित कोड और यह अच्छी तरह से काम:

[TestMethod] 
    public void TestMethod() 
    { 
     // The dispatcher thread 
     var t = new Thread(() => 
     { 
      var app = new App(); 
      // Corrects the error "System.IO.IOException: Assembly.GetEntryAssembly() returns null..." 
      App.ResourceAssembly = app.GetType().Assembly; 
      app.InitializeComponent(); 

      app.Run(); 
     }); 

     // Configure the thread 
     t.SetApartmentState(ApartmentState.STA); 
     t.Start(); 
     t.Join(); 
    } 

संपादित

अपने कोड को देखते हुए मुझे विश्वास है कि बयान SynchronizationContext को समझदार विंडो उदाहरण के निर्माण है, नहीं निर्माण आपके व्यूमोडेल का (जब तक आपका व्यूमोडेल व्यू तर्क से संबंधित नहीं होता है और नियंत्रण को तत्काल करता है, ऐसा कुछ नहीं करना चाहिए)। तो आप ऐप के थ्रेड पर विंडो के त्वरण को स्थानांतरित करने का प्रयास कर सकते हैं। कुछ इस तरह:

[TestMethod] 
    public void TestMethod3() 
    { 
     // Creates the viewmodel with the necessary infomation wherever 
        // you need to. 
     MyViewModel viewModel = new MyViewModel(string infoFromOffice); 

     // The dispatcher thread 
     var t = new Thread(() => 
     { 
      var app = new App(); 
      // Corrects the error "System.IO.IOException: Assembly.GetEntryAssembly() returns null..." 
      App.ResourceAssembly = app.GetType().Assembly; 
      app.InitializeComponent(); 

      // Creates the Window in the App's Thread and pass the information to it 
      MyWindow view = new MyWindow(); 
      view.DataContext = viewModel; 

      app.Run(view); 
     }); 

     // Configure the thread 
     t.SetApartmentState(ApartmentState.STA); 
     t.Start(); 
     t.Join(); 
    } 
+0

धन्यवाद, यह एक उपयोगी उदाहरण है लेकिन समस्या का समाधान नहीं करता है। यहां ऐप को कॉल करने के बाद दृश्य मॉडल बनाए जाते हैं। रुन()। क्योंकि मुझे अपने व्यू मॉडल को कुछ जानकारी पास करने की ज़रूरत है क्योंकि इसे ऐप पर कॉल करने से पहले तुरंत चालू किया जाना चाहिए। रुन()। इसका मतलब है कि दृश्य मॉडल के निर्माण के दौरान, कोई प्रेषक नहीं है, जो सिंक्रनाइज़ेशन कॉन्टेक्स्ट.क्यूरेंट प्राप्त करने के साथ-साथ समस्याओं का कारण बन रहा है। – Coder1095

+0

मेरा मानना ​​है कि समस्या खिड़की के इरादे से है। संपादित उत्तर देखें। –

+0

"जब तक आपका व्यूमोडेल व्यू तर्क से संबंधित नहीं होता है और नियंत्रण को तत्काल करता है, तो ऐसा कुछ नहीं करना चाहिए"। मुझे लगता है कि यह यहाँ कुंजी है। मेरा प्रोग्राम डेटाबेस क्वेरी करने के लिए पृष्ठभूमि थ्रेड (कार्य) का उपयोग करता है और फिर UI थ्रेड के माध्यम से UI को अद्यतन करता है। यदि मैं दृश्य मॉडल कन्स्ट्रक्टर (ऐप.रुन() पर कॉल से पहले) में से किसी एक कार्य का उपयोग करता हूं तो यह विफल हो जाता है क्योंकि सिंक्रनाइज़ेशन कॉन्टेक्स्ट.क्यूरेंट शून्य है। मुझे लगता है कि फिक्स सिर्फ दृश्य मॉडल कन्स्ट्रक्टर में डेटाबेस क्वेरी नहीं करने के लिए है। इसके साथ मेरी मदद करने के लिए धन्यवाद। – Coder1095

1

यहां है एक अलग संस्करण डोमेन और यूआई थ्रेड के तहत wpf एप्लिकेशन को कई बार खोलने के लिए एप्लिकेशन डोमेन का उपयोग कर एक संस्करण। एक कार्यालय addin में इसका इस्तेमाल किया। प्रत्येक बार स्टार्टअप कहा जाता है आपको एक नया एप्लीकेशन मिलता है। सत्यापित नहीं किया है कि wpf ऐप बंद होने पर थ्रेड बंद हो जाएंगे।

http://eprystupa.wordpress.com/2008/07/31/running-multiple-wpf-applications-in-the-same-process-using-appdomains/

सार्वजनिक वर्ग WpfHelper {

public static void Startup() 
    { 
     var appDomainSetup = new AppDomainSetup() 
     { 
      ApplicationBase = Path.GetDirectoryName(typeof(WpfHelper).GetType().Assembly.Location) 
     }; 

     AppDomain domain = AppDomain.CreateDomain(DateTime.Now.ToString(), null, appDomainSetup); 

     CrossAppDomainDelegate action =() => 
     { 
      Thread thread = new Thread(() => 
      { 
       var app = new WpfApplication.App(); 

       WpfApplication.App.ResourceAssembly = app.GetType().Assembly; 

       app.MainWindow = new WpfApplication.MainWindow(); 
       app.MainWindow.Show(); 
       app.Run(); 
      }); 

      thread.SetApartmentState(ApartmentState.STA); 
      thread.Start(); 

     }; 

     domain.DoCallBack(action); 
    } 

}

जिज्ञासा से बाहर
संबंधित मुद्दे