WPF ব্যবহারকারী নিয়ন্ত্রণগুলি নিষ্পত্তি করা


119

আমি একটি কাস্টম ডাব্লুপিএফ ব্যবহারকারী নিয়ন্ত্রণ তৈরি করেছি যা তৃতীয় পক্ষের দ্বারা ব্যবহার করার উদ্দেশ্যে is আমার নিয়ন্ত্রণে একটি বেসরকারী সদস্য রয়েছে যা ডিসপোজেবল, এবং আমি নিশ্চিত করতে চাই যে এর উইন্ডো / অ্যাপ্লিকেশনটি বন্ধ হয়ে গেলে এর নিষ্পত্তি পদ্ধতিটি সর্বদা কল হয়ে যায়। তবে ইউজারকন্ট্রোল নিষ্পত্তিযোগ্য নয়। আমি আইডিআইপোজেবল ইন্টারফেস বাস্তবায়ন এবং আনলোড লোড ইভেন্টটিতে সাবস্ক্রাইব করার চেষ্টা করেছি তবে হোস্ট অ্যাপ্লিকেশন বন্ধ হয়ে গেলে ফোন করা হয় না। যদি সম্ভব হয় তবে, আমি আমার নিয়ন্ত্রণের গ্রাহকদের নির্দিষ্ট ডিসপোজ পদ্ধতিতে কল করার কথা মনে করে নির্ভর করতে চাই না।

 public partial class MyWpfControl : UserControl
 {
     SomeDisposableObject x;

     // where does this code go?
     void Somewhere() 
     {
         if (x != null)
         {
             x.Dispose();
             x = null;
         }

     }
 }

আমি এখনও অবধি খুঁজে পাওয়া একমাত্র সমাধান হ'ল ডিসপ্যাচারের শাটডাউনস্টার্ড ইভেন্টটিতে সাবস্ক্রাইব করা। এটি কি যুক্তিসঙ্গত পন্থা?

this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;

ব্যবহারকারী নিয়ন্ত্রণের আনলোড হওয়া ইভেন্ট সম্পর্কে কী?
আকজোশি

2
@akjoshi: এমএসডিএন বলেছে যে: লোড করা ইভেন্টটি মোটেও উত্থাপিত হতে পারে না। এবং এটি একাধিকবার ট্রিগার হতে পারে, এটি তখনই যখন ব্যবহারকারী থিম পরিবর্তন করে।
দুদু

আপনি যখন আপনার ব্যবহারকারীর নিয়ন্ত্রণে আইডিস্পোজেবল ইন্টারফেসটি প্রয়োগ করতে পারেন, তখন কোনও গ্যারান্টি নেই যে আপনার তৃতীয় পক্ষটি আপনার নিষ্পত্তি প্যাটার্ন প্রয়োগের নিষ্পত্তি পদ্ধতিটিকে কল করবে। আপনি যদি স্থানীয় উত্সগুলিতে ধরে রাখেন (যেমন একটি ফাইল স্ট্রিম), আপনার চূড়ান্তকরণকারীটি ব্যবহার করা উচিত।
ফিলিপ

উত্তর:


57

আকর্ষণীয় ব্লগ পোস্ট এখানে:

http://geekswithblogs.net/cskardon/archive/2008/06/23/dispose-of-a-wpf-usercontrol-ish.aspx

এটি ডিসপ্যাচারে সাবস্ক্রাইব করার কথা উল্লেখ করে your আপনার সংস্থানগুলি নিষ্পত্তি করার জন্য শাটডাউন স্টার্ট করা।


1
আমি আশা করছিলাম যে এর থেকে আরও পরিষ্কার উপায় থাকবে তবে এখনকার মতো মনে হচ্ছে এটি করা ভাল।
মার্ক হিথ

35
তবে অ্যাপ্লিকেশনটি মারা যাওয়ার আগে ইউজারকন্ট্রোল মারা গেলে কী হবে? অ্যাপ্লিকেশনটি কেবল তখনই পাঠানো হবে যখন ঠিক আছে, তাই না?
রবার্ট জেপ্পেসেন

15
কারণ অনেকগুলি নিয়ন্ত্রণ COM উপাদানগুলি বা অন্যান্য ব্যবস্থাপনিত সংস্থানগুলিকে পুনরায় ব্যবহার করে যা অনির্দিষ্টকালের জন্য ঝুলন্ত অবস্থায় রেখে দেওয়া বা কোনও থ্রেড পুলের থ্রেডে চূড়ান্ত করা হয়, এবং নির্ণয়জনিত অবসান আশা / প্রয়োজনীয় করে require
নিউট্রিনো

1
একটি উইন্ডোজ স্টোর অ্যাপে, শাটডাউনস্টার্ড বিদ্যমান নেই।
সিউর

7
বা আপনাকে ইভেন্ট হ্যান্ডলারগুলি
ডিফারেন্স

40

Dispatcher.ShutdownStartedইভেন্টটি কেবলমাত্র আবেদন শেষে বরখাস্ত করা হয়। নিয়ন্ত্রণ যখন ব্যবহারের বাইরে চলে যায় তখনই তা নিষ্পত্তি যুক্তিকে কল করা ভাল। অ্যাপ্লিকেশন রানটাইমের সময় নিয়ন্ত্রণ অনেকবার ব্যবহার করা হয় বিশেষত এটি সংস্থানগুলি মুক্ত করে। সুতরাং আইওউইন্টের সমাধানটি পছন্দনীয়। কোডটি এখানে:

public MyWpfControl()
{
     InitializeComponent();
     Loaded += (s, e) => { // only at this point the control is ready
         Window.GetWindow(this) // get the parent window
               .Closing += (s1, e1) => Somewhere(); //disposing logic here
     };
}

একটি উইন্ডোজ স্টোর অ্যাপে গেট উইন্ডো () বিদ্যমান নেই।
Curur

ব্রাভো, সবচেয়ে বড় উত্তর।
নিক

8
কোর: একটি উইন্ডোজ স্টোর অ্যাপে আপনি ডাব্লুপিএফ ব্যবহার করছেন না
অ্যালান বালজেউ

3
যদি আরও বেশি উইন্ডোজ জড়িত থাকে এবং প্রধানটি কখন বন্ধ হয় না? অথবা আপনার নিয়ন্ত্রণ পৃষ্ঠাতে হোস্ট করা হয়েছে যা একাধিকবার লোড / আনলোড হয়? দেখুন: stackoverflow.com/a/14074116/1345207
L.Trabacchin

1
উইন্ডো খুব ঘন ঘন বন্ধ না হতে পারে। নিয়ন্ত্রণটি যদি কোনও তালিকার আইটেমের অংশ হয় তবে এর প্যারেন্ট উইন্ডোটি বন্ধ না হওয়া পর্যন্ত অনেকগুলি তৈরি / ধ্বংস করা হবে।
হারানো

15

আপনি ধ্বংসকারী ব্যবহার করে যত্নবান হতে হবে। এটি জিসি ফাইনালাইজার থ্রেডে কল করবে। কিছু ক্ষেত্রে যে সংস্থানগুলি আপনার নিখরচায় হতে পারে সেগুলি তাদের তৈরি করা থেকে আলাদা থ্রেডে ছেড়ে দেওয়া পছন্দ করতে পারে না।


1
এই সতর্কতার জন্য আপনাকে ধন্যবাদ। এই আমার ঘটনা ঠিক ছিল! অ্যাপ্লিকেশন: devenv.exe ফ্রেমওয়ার্ক সংস্করণ: v4.0.30319 বিবরণ: প্রক্রিয়াটি একটি নিয়ন্ত্রণহীন ব্যতিক্রমের কারণে সমাপ্ত হয়েছিল। ব্যতিক্রম তথ্য: সিস্টেম.অনুষ্ঠানিক অপারেশন এক্সেকশন স্ট্যাক: মাই কন্ট্রোল.ফাইনালাইজ () আমার সমাধানটি ছিল চূড়ান্তকরণকারী থেকে কোডটি
শাটডাউনস্টার্টে

10

আমি ডাব্লুপিএফ ব্যবহারকারীকন্ট্রোলগুলিতে একটি লোডিং ইভেন্ট সরবরাহ করতে নিম্নলিখিত ইন্টারঅ্যাক্টিভিটি আচরণ ব্যবহার করি। আপনি ব্যবহারকারীর নিয়ন্ত্রণ XAML এ আচরণটি অন্তর্ভুক্ত করতে পারেন। সুতরাং আপনি প্রতিটি একক ব্যবহারকারীকে এই যুক্তি না রেখে কার্যকারিতা রাখতে পারেন।

এক্সএএমএল ঘোষণা:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<i:Interaction.Behaviors>
    <behaviors:UserControlSupportsUnloadingEventBehavior UserControlClosing="UserControlClosingHandler" />
</i:Interaction.Behaviors>

কোডবিহ্যান্ড হ্যান্ডলার:

private void UserControlClosingHandler(object sender, EventArgs e)
{
    // to unloading stuff here
}

আচরণ কোড:

/// <summary>
/// This behavior raises an event when the containing window of a <see cref="UserControl"/> is closing.
/// </summary>
public class UserControlSupportsUnloadingEventBehavior : System.Windows.Interactivity.Behavior<UserControl>
{
    protected override void OnAttached()
    {
        AssociatedObject.Loaded += UserControlLoadedHandler;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Loaded -= UserControlLoadedHandler;
        var window = Window.GetWindow(AssociatedObject);
        if (window != null)
            window.Closing -= WindowClosingHandler;
    }

    /// <summary>
    /// Registers to the containing windows Closing event when the UserControl is loaded.
    /// </summary>
    private void UserControlLoadedHandler(object sender, RoutedEventArgs e)
    {
        var window = Window.GetWindow(AssociatedObject);
        if (window == null)
            throw new Exception(
                "The UserControl {0} is not contained within a Window. The UserControlSupportsUnloadingEventBehavior cannot be used."
                    .FormatWith(AssociatedObject.GetType().Name));

        window.Closing += WindowClosingHandler;
    }

    /// <summary>
    /// The containing window is closing, raise the UserControlClosing event.
    /// </summary>
    private void WindowClosingHandler(object sender, CancelEventArgs e)
    {
        OnUserControlClosing();
    }

    /// <summary>
    /// This event will be raised when the containing window of the associated <see cref="UserControl"/> is closing.
    /// </summary>
    public event EventHandler UserControlClosing;

    protected virtual void OnUserControlClosing()
    {
        var handler = UserControlClosing;
        if (handler != null) 
            handler(this, EventArgs.Empty);
    }
}

5
আমি এখানে একটি পতাকা বাড়াব ... উইন্ডো বন্ধ হওয়া যদি অন্য কোনও কিছু বাতিল করে দেয় তবে (সম্ভবত আপনার নিয়ন্ত্রণের পরে সাবস্ক্রাইব করা e.Cancelএটি আপনার WindowClosingHandlerপ্রতিনিধি পৌঁছানোর পরেও মিথ্যা )? আপনার নিয়ন্ত্রণ "আনলোড করা" হবে এবং উইন্ডোটি এখনও খোলা থাকবে। আমি অবশ্যই Closedইভেন্টে এটি করব, কোনওটিতে নয় Closing
জেএলসি

6

আমার পরিস্থিতিটি কিছুটা আলাদা, তবে উদ্দেশ্যটি একই রকম আমি জানতে চাই যখন আমার ব্যবহারকারী নিয়ন্ত্রণের হোস্টিং প্যারেন্ট উইন্ডোটি বন্ধ হবে / বন্ধ হিসাবে দৃশ্যটি (অর্থাত্ আমার ব্যবহারকারীকন্ট্রোল) উপস্থাপকদের অনক্লোজভিউকে কিছু কার্যকারিতা সম্পাদন করতে এবং পরিষ্কার পরিচ্ছন্ন করতে অনুরোধ করবে। (ভাল আমরা একটি ডাব্লুপিএফ PRISM অ্যাপ্লিকেশনটিতে একটি এমভিপি প্যাটার্ন বাস্তবায়ন করছি)।

আমি ঠিক বুঝতে পেরেছি যে ইউজারকন্ট্রোলের লোডড ইভেন্টে আমি প্যারেন্ট উইন্ডো ক্লোসিংয়ের পদ্ধতিটি প্যারেন্ট উইন্ডোজ বন্ধের ইভেন্টটিতে রাখতে পারি। প্যারেন্ট উইন্ডোটি বন্ধ হয়ে যাওয়ার সাথে সাথে আমার ইউজারকন্ট্রলটি সচেতন হতে পারে এবং সেই অনুসারে কাজ করুন!


0

আমি ভাবছি আনলোডকে সমস্ত বলা হয় তবে শক্ত অবস্থানে 4.7-এ রয়েছে। তবে, আপনি। নেট এর পুরানো সংস্করণগুলি নিয়ে ঘুরে দেখছেন, আপনার লোডিং পদ্ধতিতে এটি করার চেষ্টা করুন:

e.Handled = true;

আমি মনে করি না লোডিং পরিচালনা না হওয়া অবধি পুরানো সংস্করণগুলি আনলোড হবে। কেবল পোস্ট করা হচ্ছে কারণ আমি অন্যকে এখনও এই প্রশ্ন জিজ্ঞাসা করছি এবং এটি প্রস্তাব হিসাবে সমাধান হিসাবে দেখেনি। আমি কেবল স্পর্শ করি year তবে, আমি অবাক হয়েছি যে এটি লোডিং শেষ না হওয়া অবধি আনডাউন না করা হিসাবে এত সহজ। দেখে মনে হচ্ছে এটি আমার জন্য কাজ করে তবে আবার নতুন করে। মনে হয় লোড হ্যান্ডলড হিসাবে চিহ্নিত না থাকলেও সর্বদা আনলোডকে কল করা উচিত।


-3

একজন ইউজারকন্ট্রোলের একটি ডেস্ট্রাক্টর রয়েছে, আপনি কেন এটি ব্যবহার করেন না?

~MyWpfControl()
    {
        // Dispose of any Disposable items here
    }

এটি কাজ করে না বলে মনে হচ্ছে। আমি কেবল সেই পদ্ধতির চেষ্টা করেছি এবং এটি কখনই ডাকা হয় না।
জেসনড

9
এটি কোনও ধ্বংসকারী নয়, এটি চূড়ান্তকরণকারী। আপনি সর্বদা একটি ফাইনালাইজার প্রয়োগ করেন এবং একটি জোড়া হিসাবে নিষ্পত্তি করুন অন্যথায় আপনি ফাঁসের ঝুঁকি নিয়ে যান।
মাইক পোস্ট

1
এবং, চূড়ান্তকরণে আপনাকে কেবল অপরিকল্পিত অবজেক্টগুলি পরিষ্কার করতে হবে তবে পরিচালিত অবজেক্টগুলি নয়, কারণ জিসি থ্রেডগুলিতে চূড়ান্তকরণগুলি অনির্ধারিত ক্রমে চালিত হয় এভাবে পরিচালিত অবজেক্টগুলি আগে চূড়ান্ত করা যেতে পারে এবং তাদের নিষ্পত্তি () এর থ্রেডের সখ্যতা থাকতে পারে।
দুদু

2
joeduffyblog.com/2005/04/08/… আমার চূড়ান্তকরণ এবং নিষ্পত্তি করার সর্বোত্তম ব্যাখ্যা। এটা সত্যিই পড়া মূল্যবান।
dss539
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.