ডাব্লুপিএফ-তে কার্সার পরিবর্তন করা কখনও কখনও কাজ করে, কখনও কখনও তা করে না


123

আমার বেশ কয়েকটি ব্যবহারকারীর নিয়ন্ত্রণগুলিতে, আমি ব্যবহার করে কার্সারটি পরিবর্তন করি

this.Cursor = Cursors.Wait;

যখন আমি কিছু ক্লিক করি।

এখন আমি বাটন ক্লিকের ডব্লিউপিএফ পৃষ্ঠায় একই জিনিসটি করতে চাই on আমি যখন আমার বোতামের ওপরে ঘোরাফেরা করি, তখন কার্সারটি একটি হাতে বদলে যায়, কিন্তু আমি যখন এটি ক্লিক করি তখন এটি অপেক্ষার কার্সারে পরিবর্তিত হয় না। আমি ভাবছি এটির সাথে যদি এটির একটি বোতাম, বা এটি একটি পৃষ্ঠা এবং ব্যবহারকারীকন্ট্রোল নয় তবে এই বিষয়টির সাথে কিছু আছে কিনা? এটিকে আজব আচরণ বলে মনে হচ্ছে।

উত্তর:


211

আপনার যদি কেবলমাত্র সেই নির্দিষ্ট পৃষ্ঠা / ব্যবহারকারীকন্ট্রোলের উপরেই অপেক্ষা করেন তবে "অপেক্ষা করুন" কার্সার হওয়ার দরকার আছে? যদি তা না হয় তবে আমি মাউস ব্যবহার করার পরামর্শ দেব ver ওভাররাইড কার্সার :

Mouse.OverrideCursor = Cursors.Wait;
try
{
    // do stuff
}
finally
{
    Mouse.OverrideCursor = null;
}

এটি আপনার অ্যাপ্লিকেশনের জন্য কার্সারটিকে কেবলমাত্র তার ইউআইর অংশের চেয়ে ওভাররাইড করে, তাই আপনি যে সমস্যাটি বর্ণনা করছেন তা চলে যায়।


আমার নিজের উত্তর মত , 3 বছর পরে (প্রায় ঠিক!) তারিখ। আমি এই প্রশ্নের উত্তরগুলি পছন্দ করি তবে সহজতমটি সর্বদা সবচেয়ে লোভনীয় :)
রবিন মাবেন

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

2
এটি যেমন পুরানো এবং যেমনটি স্বীকৃত তবে এটি সঠিক উত্তর নয়। অ্যাপ্লিকেশন কার্সরকে ওভাররাইড করা একটি নিয়ন্ত্রণ কার্সারকে ওভাররাইড করার চেয়ে আলাদা (এবং দ্বিতীয়টিতে ডাব্লুপিএফ-এ সমস্ত সমস্যা রয়েছে)। অ্যাপ্লিকেশন কার্সরকে ওভাররাইড করা বাজে পার্শ্ব প্রতিক্রিয়া ফেলতে পারে, উদাহরণস্বরূপ, একটি পপিং আপ (ত্রুটি) বার্তা বাক্সটি একই ওভাররাইড করা কার্সারটিকে ভুলভাবে ব্যবহার করতে বাধ্য হতে পারে যখন উদ্দেশ্যটি কেবল ওভাররাইড করার সময় যখন মাউসটি আসল এবং সক্রিয় নিয়ন্ত্রণের উপর ঘোরাফেরা করছিল।
গ্যাবার

64

আমাদের প্রয়োগে এটি করার একটি উপায় হ'ল আইডিস্পোজেবল এবং তারপরে using(){}যখন কার্সারটি হয়ে যায় তখন তা পুনরায় সেট হয়ে যায় তা নিশ্চিত করতে ব্লকগুলি ব্যবহার করে।

public class OverrideCursor : IDisposable
{

  public OverrideCursor(Cursor changeToCursor)
  {
    Mouse.OverrideCursor = changeToCursor;
  }

  #region IDisposable Members

  public void Dispose()
  {
    Mouse.OverrideCursor = null;
  }

  #endregion
}

এবং তারপরে আপনার কোডে:

using (OverrideCursor cursor = new OverrideCursor(Cursors.Wait))
{
  // Do work...
}

ওভাররাইডটি শেষ হবে যখন হয়: ব্যবহারের বিবৃতিটির শেষে পৌঁছেছে বা; যদি কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় এবং নিয়ন্ত্রণ বিবৃতি শেষ হওয়ার আগে বিবৃতিটিকে অবরুদ্ধ করে দেয়।

হালনাগাদ

কার্সার ঝাঁকুনি প্রতিরোধ করতে আপনি এটি করতে পারেন:

public class OverrideCursor : IDisposable
{
  static Stack<Cursor> s_Stack = new Stack<Cursor>();

  public OverrideCursor(Cursor changeToCursor)
  {
    s_Stack.Push(changeToCursor);

    if (Mouse.OverrideCursor != changeToCursor)
      Mouse.OverrideCursor = changeToCursor;
  }

  public void Dispose()
  {
    s_Stack.Pop();

    Cursor cursor = s_Stack.Count > 0 ? s_Stack.Peek() : null;

    if (cursor != Mouse.OverrideCursor)
      Mouse.OverrideCursor = cursor;
  }

}

2
ব্যবহার অংশের সাথে দুর্দান্ত সমাধান। আমি আসলে আমাদের কয়েকটি প্রকল্পে হুবহু একই রকম লিখেছি (স্ট্যাক ব্যতীত, এটি)। একটি জিনিস যা আপনি ব্যবহারের ক্ষেত্রে সহজ করতে পারবেন তা হ'ল কেবল লিখুন: (নতুন ওভাররাইডকার্সার (কার্সার্স.ওয়েট)) {// ডু স্টাফ it পরিবর্তে এটি ভেরিয়েবল নির্ধারণের পরিবর্তে আপনি সম্ভবত ব্যবহার করবেন না।
অলি

1
কোন দরকার নেই. আপনি যদি এটি সেট Mouse.OverrideCursorকরে থাকেন nullতা সেট না করা থাকলে এবং সিস্টেম কার্সারকে আর ওভাররাইড করে না। যদি আমি বর্তমান কার্সারটি সরাসরি (যদি ওভাররাইড না করে) পরিবর্তন করে থাকি তবে সমস্যা হতে পারে।
ডেনিস

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

2
@ সিমনগিলবি যা সত্যই সম্ভব - এটি 10 ​​বছর আগে আমার লেখা ছিল এমন সমস্যা ছিল না। যদি আপনি কোনও সমাধান খুঁজে পান, সম্ভবত একটি ব্যবহার করে ConcurrentStack<Cursor>, উপরের উত্তরটি সম্পাদনা করতে বা আপনার নিজের যুক্ত করতে নির্দ্বিধায়।
ডেনিস

2
@ ডেনিস আমি আসলে কিছুদিন আগে এটি লিখেছিলাম (এ কারণেই আমি এসও এর মাধ্যমে দেখছিলাম)। আমি কনকন্টারস্ট্যাকের সাথে খেলেছি, তবে এটি ভুল সংগ্রহ হিসাবে প্রমাণিত হয়েছে। স্ট্যাক কেবল আপনাকে শীর্ষে পপ অফ করতে দেয়। এক্ষেত্রে আপনি স্ট্যাকের মধ্য থেকে সরিয়ে নিতে চান যদি সেই কর্সারটিকে স্ট্যাকের শীর্ষটি নিষ্পত্তি করার আগেই নিষ্পত্তি করা হয়। সাম্প্রতিক অ্যাক্সেস পরিচালনার জন্য আমি কেবলমাত্র <T> রিডার রাইটারলকস্লিম ব্যবহার করে তালিকাটি ব্যবহার করে শেষ করেছি।
সাইমন গিলবি

38

অপেক্ষার কার্সর সক্ষম করতে আপনি বোতামে ডেটা ট্রিগার (একটি ভিউ মডেল সহ) ব্যবহার করতে পারেন।

<Button x:Name="NextButton"
        Content="Go"
        Command="{Binding GoCommand }">
    <Button.Style>
         <Style TargetType="{x:Type Button}">
             <Setter Property="Cursor" Value="Arrow"/>
             <Style.Triggers>
                 <DataTrigger Binding="{Binding Path=IsWorking}" Value="True">
                     <Setter Property="Cursor" Value="Wait"/>
                 </DataTrigger>
             </Style.Triggers>
         </Style>
    </Button.Style>
</Button>

ভিউ-মডেল থেকে কোডটি এখানে:

public class MainViewModel : ViewModelBase
{
   // most code removed for this example

   public MainViewModel()
   {
      GoCommand = new DelegateCommand<object>(OnGoCommand, CanGoCommand);
   }

   // flag used by data binding trigger
   private bool _isWorking = false;
   public bool IsWorking
   {
      get { return _isWorking; }
      set
      {
         _isWorking = value;
         OnPropertyChanged("IsWorking");
      }
   }

   // button click event gets processed here
   public ICommand GoCommand { get; private set; }
   private void OnGoCommand(object obj)
   {
      if ( _selectedCustomer != null )
      {
         // wait cursor ON
         IsWorking = true;
         _ds = OrdersManager.LoadToDataSet(_selectedCustomer.ID);
         OnPropertyChanged("GridData");

         // wait cursor off
         IsWorking = false;
      }
   }
}

4
ডাউনটাও আমি পাই না। এই উত্তরটি কার্যকর যখন আপনি এমভিভিএম ব্যবহার করেন (সুতরাং কোনও কোড-পিছনে নেই) এবং নির্দিষ্ট নিয়ন্ত্রণের জন্য কার্সারটি নিয়ন্ত্রণ করতে চান। খুব দরকারী.
সাইমন গিলবি

4
আমি এমভিভিএমের সুবিধাগুলি লাভবান করছি এবং এটিই সঠিক উত্তর।
g1ga 22

আমি এই সমাধানটি পছন্দ করি কারণ আমি বিশ্বাস করি এটি এমভিভিএম, ভিউ মডেলস ইত্যাদির সাথে আরও ভাল কাজ করবে
রোড

এই কোডটি দিয়ে আমি যে সমস্যাটি দেখছি তা হ'ল কার্সারগুলি "অপেক্ষা করুন" কেবল তখনই মাউসটি বোতামের উপর দিয়ে চলেছে, তবে আপনি যখন মাউসটি সরিয়ে নিয়েছেন এটি একটি "তীর" হিসাবে ফিরে আসে।
স্পাইডারম্যান

7

যদি আপনার অ্যাপ্লিকেশনটি অ্যাসিঙ্ক স্টাফ ব্যবহার করে এবং আপনি মাউসের কার্সারে ফিড করছেন তবে আপনি সম্ভবত এটি কেবল প্রধান ইউআই থ্রেডে করতে চান। আপনি এটির জন্য অ্যাপের ডিসপ্যাচার থ্রেড ব্যবহার করতে পারেন:

Application.Current.Dispatcher.Invoke(() =>
{
    // The check is required to prevent cursor flickering
    if (Mouse.OverrideCursor != cursor)
        Mouse.OverrideCursor = cursor;
});

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.