Nasıl yapılır: ContextMenuOpening Olayını İşleme
Olay, görüntülenmeden önce var olan bir bağlam menüsünü ayarlamak veya aksi takdirde olay verisinde özelliğini olarak ayarlayan menüyü gizlemek için bir ContextMenuOpening Handled uygulamada true işleniyor olabilir. Olay verisinde ayarının tipik nedeni, menüyü tamamen yeni bir nesneyle değiştirmektir. Bu, bazen işlemi iptal etmek ve yeni bir açık Handled true ContextMenu başlatmayı gerektirir. Olay için işleyiciler yazarsanız, denetimler için bağlam menülerini açmak ve konumlandırmak için genel olarak sorumlu olan hizmetle denetim arasındaki zamanlama ContextMenuOpening ContextMenu sorunlarının farkında olursanız. Bu konu başlığında, çeşitli bağlam menüsü açma senaryolarına ilişkin bazı kod teknikleri ve zamanlama sorunu devreye girmektedir.
Olayın işlenmesi için çeşitli senaryolar ContextMenuOpening vardır:
Görüntülenmeden önce menü öğelerini ayarlama.
Görüntülenmeden önce tüm menüyü değiştirme.
Mevcut bağlam menülerini tamamen gizleme ve bağlam menüsü görüntülememe.
Örnek
Görüntülemeden Önce Menü Öğelerini Ayarlama
Mevcut menü öğelerini ayarlamak oldukça basittir ve muhtemelen en yaygın senaryodur. Bunu, uygulamanıza ilişkin geçerli durum bilgilerine veya bağlam menüsünün isten bulunduğu nesnede özellik olarak kullanılabilen belirli durum bilgilerine yanıt olarak bağlam menüsü seçenekleri eklemek veya çıkarmak için yapabilirsiniz.
Genel teknik, sağ tık kullanılan denetim olan olayın kaynağını almak ve özelliği buradan ContextMenu almaktır. Genellikle menüde mevcut olan bağlam menüsü öğelerini görmek ve ardından koleksiyona veya koleksiyondan uygun yeni öğeleri eklemek veya kaldırmak için Items MenuItem koleksiyonu kontrol etmek istersiniz.
void AddItemToCM(object sender, ContextMenuEventArgs e)
{
//check if Item4 is already there, this will probably run more than once
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
foreach (MenuItem mi in cm.Items)
{
if ((String)mi.Header == "Item4") return;
}
MenuItem mi4 = new MenuItem();
mi4.Header = "Item4";
fe.ContextMenu.Items.Add(mi4);
}
Görüntülemeden Önce Tüm Menüyü Değiştirme
Alternatif bir senaryo ise bağlam menüsünün tamamını değiştirmek istemedir. Mevcut bağlam menüsünün her öğesini kaldırmak ve sıfır öğesiyle başlayan yenilerini eklemek için yukarıdaki kodun bir varyasyonu da kullanabilirsiniz. Ancak bağlam menüsündeki tüm öğeleri değiştirmek için daha sezgisel bir yaklaşım, yeni bir oluşturmak, bunu öğelerle doldurmak ve ardından denetimin özelliğini yeni ContextMenu FrameworkElement.ContextMenu olarak ContextMenu ayarlamaktır.
Aşağıda, bir 'i değiştirmek için basit işleyici kodu ve ardından ve ve ContextMenu 2. Kod, örnek işleyicilerden biri tarafından çağrıldıklarından ayrılmış olan BuildMenu özel bir yönteme başvurur.
void HandlerForCMO(object sender, ContextMenuEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
}
ContextMenu BuildMenu()
{
ContextMenu theMenu = new ContextMenu();
MenuItem mia = new MenuItem();
mia.Header = "Item1";
MenuItem mib = new MenuItem();
mib.Header = "Item2";
MenuItem mic = new MenuItem();
mic.Header = "Item3";
theMenu.Items.Add(mia);
theMenu.Items.Add(mib);
theMenu.Items.Add(mic);
return theMenu;
}
Ancak, için bu işleyici stilini kullanırsanız, ayarda bulunduğu nesnenin önceden var olan bir bağlam menüsü yoksa bir zamanlama sorunu ContextMenuOpening ContextMenu ortaya çıkarabilirsiniz. Kullanıcı bir denetime sağ tıkladığında, ContextMenuOpening mevcut boş veya null olsa bile ortaya ContextMenu çıkar. Ancak bu durumda, kaynak ContextMenu öğede ayar her ne olursa olsun görüntülenmek için çok geç gelir. Ayrıca, kullanıcı ikinci kez sağ tıklarsa, bu kez yeniniz görüntülendiğinde değer null değildir ve işleyiciniz doğru şekilde değiştirilir ve işleyici ikinci kez çalıştırıldıkları zaman ContextMenu menüyü görüntüler. Bu, iki olası geçici çözüm önerir:
İşleyicilerin her zaman en az bir yer tutucusu olan ve işleyici koduyla değiştirilmesini istediğiniz ContextMenuOpening ContextMenu denetimlerde çalıştırıldıklarına emin olur. Bu durumda, yine de önceki örnekte gösterilen işleyiciyi kullanabilirsiniz, ancak genellikle ilk işaretlemede bir yer ContextMenu tutucu atamak gerekir:
<StackPanel> <Rectangle Fill="Yellow" Width="200" Height="100" ContextMenuOpening="HandlerForCMO"> <Rectangle.ContextMenu> <ContextMenu> <MenuItem>Initial menu; this will be replaced ...</MenuItem> </ContextMenu> </Rectangle.ContextMenu> </Rectangle> <TextBlock>Right-click the rectangle above, context menu gets replaced</TextBlock> </StackPanel>Başlangıç değerinin ContextMenu bazı ön mantığa göre null olabileceğini varsayalım. Null olup olmadığını kontrol etmek veya işleyicinizin en az bir kez çalıştırıp çalıştırı olmadığını kontrol etmek için kodunda ContextMenu bir bayrak kullanabilirsiniz. görüntülenecek olduğunu ContextMenu varsaymanıza göre, işleyiciniz olay verisinde Handled
trueolarak ayarlar. Bağlam menüsü görüntüsünden sorumlu olan için olay verisinde değeri, olayı başlatan bağlam menüsü/denetim bileşimi için ekranı iptal etme ContextMenuServicetrueisteğini temsil Handled eder.
Artık şüpheli olabilecek bağlam menüsünü bastırmış olduğunuza göre, sonraki adım yeni bir tane sağlamak ve sonra bunu görüntülemektir. Yenisini ayarlamak temelde önceki işleyiciyle aynıdır: yeni bir derleme ve denetim ContextMenu kaynağının özelliğini bu işleyiciyle FrameworkElement.ContextMenu ayarlarsanız. Ek adım, ilk denemeyi gizlemeye çalıştığınız için bağlam menüsünün görüntülenmeye zor olmasıdır. Ekranı zorlamak için özelliğini Popup.IsOpen işleyicinin içinde true olarak ayarlayın. bunu yaparken dikkatli olun çünkü işleyicide bağlam menüsünün açılması olayı yeniden ContextMenuOpening başlatıyor. İşleyicinizi yeniden girmeniz, son derece tekrarlayıcı hale gelir. Bu nedenle, bir olay işleyicisi içinde bir bağlam menüsü açarsanız her zaman bayrağı null denetlemeniz veya ContextMenuOpening kullanmanız gerekir.
Mevcut Bağlam Menülerini Gizleme ve Bağlam Menüsü Görüntülememe
Son senaryo, bir menüyü tamamen bastıran bir işleyici yazmak yaygın bir durumdur. Verilen bir denetimin bağlam menüsünü görüntülemesi gerekmiyorsa, bunu sağlamak için büyük olasılıkla bir kullanıcı bunu tam olarak istenende menüyü gizlemenin daha uygun yolları vardır. Ancak bir bağlam menüsünü gizlemeye ve hiçbir şey göstermemenize yardımcı olmak için işleyiciyi kullanmak için işleyicinizin olay verisinde Handled true olarak ayarlanmış olması gerekir. Bağlam ContextMenuService menüsünü görüntülemekle sorumlu olan, denetimde ortaya çıkan olayın olay verilerini kontrol etmektir. Olay rotanın Handled herhangi bir yerinde işaretlenmişse, olayı başlatan bağlam menüsü açma eylemi gizlenr.
void HandlerForCMO2(object sender, ContextMenuEventArgs e)
{
if (!FlagForCustomContextMenu)
{
e.Handled = true; //need to suppress empty menu
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
FlagForCustomContextMenu = true;
fe.ContextMenu.IsOpen = true;
}
}
}