يمر أصل ContextMenu إلى قيادة WPF
سؤال
ومشكلة مثيرة للاهتمام تتعلق بإطلاق الأوامر من عناصر القائمة السياق ...
وأريد أن إطلاق الأمر لإدراج صف في بلدي السيطرة، InsertRowCmd. يحتاج هذا الأمر لتعرف من أين إدراج الصف.
وأتمكن من استخدام Mouse.GetPosition ()، ولكن هذا سيحصل لي موقف الماوس حاليا، والتي ستكون على عنصر القائمة. أريد الحصول على أصل قائمة السياق بدلا من ذلك.
هل هناك أي واحد أي اقتراحات بشأن كيفية تمرير أصل قائمة السياق كمعلمة إلى الأمر؟
ونموذج التعليمات البرمجية:
<UserControl x:Name="MyControl">
<!--...-->
<ContextMenu x:Name="menu">
<MenuItem Header="Insert Row" Command="{x:Static customCommands:MyCommands.InsertRowCmd}" CommandParameter="?"/>
</ContextMenu>
</UserControl>
وأفكاري الحالية هي كما يلي:
و-استخدام انقر معالج بدلا بحيث يمكنني العثور على الأصل في التعليمات البرمجية. المشكلة هي أنني بعد ذلك للتعامل مع تمكين / تعطيل.
ومقبض الحدث انقر فوق وحفظ أصل قائمة السياق. تمرير هذه المعلومات المحفوظة في الأمر. ولقد تحققت هذه النقرة أحداث الحريق قبل تنفيذ الأمر.
وأي أفكار؟
تعديل:
وأنا باستخدام جوش سميث <لأ href = "http://www.codeproject.com/KB/WPF/VMCommanding.aspx؟fid=1521948&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2696866" يختلط = "noreferrer"> CommandSinkBinding لمسار قيادة التعامل مع في صفي ViewModel. ذلك الرمز الذي يعالج تنفيذ الأمر يعرف شيئا عن الرأي.
المحلول
وستحتاج إلى استخدام TranslatePoint
لترجمة العلوية اليسرى (0، 0) من ContextMenu
إلى تنسيق في الشبكة التي تحتوي على. هل يمكن أن تفعل ذلك عن طريق ربط CommandParameter
إلى ContextMenu
واستخدام محول:
CommandParameter="{Binding IsOpen, ElementName=_menu, Converter={StaticResource PointConverter}}"
وثمة نهج آخر سيكون سلوك المرفقة يقوم بتحديث خاصية للقراءة فقط المرفقة نوع Point
تلقائيا كلما فتحت ContextMenu
. أن استخدام ننظر بشيء من هذا القبيل:
<ContextMenu x:Name="_menu" local:TrackBehavior.TrackOpenLocation="True">
<MenuItem Command="..." CommandParameter="{Binding Path=(local:TrackBehavior.OpenLocation), ElementName=_menu}"/>
</ContextMenu>
وهكذا الملكية TrackOpenLocation
المرفقة يفعل عمل المترتبة على ContextMenu
وتحديث خاصية المرفق الثاني (OpenLocation
) كلما فتح ContextMenu
. ثم MenuItem
يمكن ربط فقط لOpenLocation
للحصول على الموقع الذي كان ContextMenu
آخر فتح.
نصائح أخرى
وبعد يوم من الإجابة كينت، وكنت له تعلق اقتراح الممتلكات وانتهى هذا (باستخدام جوش سميث <لأ href = "http://joshsmithonwpf.wordpress.com/2008/08/30/introduction-to-attached -behaviors / "يختلط =" noreferrer "> مثال لسلوكيات المرفقة ):
public static class TrackBehavior
{
public static readonly DependencyProperty TrackOpenLocationProperty = DependencyProperty.RegisterAttached("TrackOpenLocation", typeof(bool), typeof(TrackBehavior), new UIPropertyMetadata(false, OnTrackOpenLocationChanged));
public static bool GetTrackOpenLocation(ContextMenu item)
{
return (bool)item.GetValue(TrackOpenLocationProperty);
}
public static void SetTrackOpenLocation(ContextMenu item, bool value)
{
item.SetValue(TrackOpenLocationProperty, value);
}
public static readonly DependencyProperty OpenLocationProperty = DependencyProperty.RegisterAttached("OpenLocation", typeof(Point), typeof(TrackBehavior), new UIPropertyMetadata(new Point()));
public static Point GetOpenLocation(ContextMenu item)
{
return (Point)item.GetValue(OpenLocationProperty);
}
public static void SetOpenLocation(ContextMenu item, Point value)
{
item.SetValue(OpenLocationProperty, value);
}
static void OnTrackOpenLocationChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var menu = dependencyObject as ContextMenu;
if (menu == null)
{
return;
}
if (!(e.NewValue is bool))
{
return;
}
if ((bool)e.NewValue)
{
menu.Opened += menu_Opened;
}
else
{
menu.Opened -= menu_Opened;
}
}
static void menu_Opened(object sender, RoutedEventArgs e)
{
if (!ReferenceEquals(sender, e.OriginalSource))
{
return;
}
var menu = e.OriginalSource as ContextMenu;
if (menu != null)
{
SetOpenLocation(menu, Mouse.GetPosition(menu.PlacementTarget));
}
}
}
ومن ثم استخدامها في XAML، كل ما تحتاجه هو:
<ContextMenu x:Name="menu" Common:TrackBehavior.TrackOpenLocation="True">
<MenuItem Command="{Binding SomeCommand}" CommandParameter="{Binding Path=(Common:TrackBehavior.OpenLocation), ElementName=menu}" Header="Menu Text"/>
</ContextMenu>
ولكن، أنا في حاجة أيضا إلى إضافة:
NameScope.SetNameScope(menu, NameScope.GetNameScope(this));
وإلى منشئ وجهة نظري، وإلا فإن ملزمة لCommandParameter
لا يمكن البحث ElementName=menu
.
وبالإضافة إلى الإجابة كينت، والتفكير في "طريقة قياسية". F.e. عندما مربع القائمة لديه ContextMenu، لا تحتاج موقف القائمة، وبسبب تعيين العنصر المحدد من قبل القائمة برزت. لذا، إذا التحكم الخاصة بك لن يكون شيء أن يحصل على "اختيار" على فوق الحق ...