سؤال

هل لاحظ أي شخص آخر أن الارتباطات باستخدام ElementName لا يتم حلها بشكل صحيح لـ MenuItem الكائنات الموجودة بداخلها ContextMenu أشياء؟تحقق من هذه العينة:

<Window x:Class="EmptyWPF.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    x:Name="window">
    <Grid x:Name="grid" Background="Wheat">
        <Grid.ContextMenu>
            <ContextMenu x:Name="menu">
                <MenuItem x:Name="menuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
                <MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
                <MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
                <MenuItem Header="Menu Item" Tag="{Binding ElementName=menuItem}" Click="MenuItem_Click"/>
            </ContextMenu>
        </Grid.ContextMenu>
        <Button Content="Menu" 
                HorizontalAlignment="Center" VerticalAlignment="Center" 
                Click="MenuItem_Click" Tag="{Binding ElementName=menu}"/>
        <Menu HorizontalAlignment="Center" VerticalAlignment="Bottom">
            <MenuItem x:Name="anotherMenuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
            <MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
            <MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
            <MenuItem Header="Menu Item" Tag="{Binding ElementName=anotherMenuItem}" Click="MenuItem_Click"/>
        </Menu>
    </Grid>
</Window>

تعمل كافة الارتباطات بشكل جيد باستثناء الارتباطات الموجودة في قائمة السياق.يقومون بطباعة خطأ في نافذة الإخراج أثناء وقت التشغيل.

هل يعرف أحد أي عمل حوله؟ما الذي يحدث هنا؟

هل كانت مفيدة؟

المحلول

ولقد وجدت الحل أبسط من ذلك بكثير.

في التعليمات البرمجية خلف لفي UserControl:

NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));

نصائح أخرى

وكما قال من قبل الآخرين، لا تحتوي على "ContextMenu" في شجرة البصرية و 'ElementName' لن تعمل ملزمة. وضع قائمة السياق في "NameScope" على النحو الذي اقترحه إجابة مقبولة يعمل فقط إذا لم يتم تعريف قائمة السياق في "DataTemplate. لقد حل هذه باستخدام {س: مرجع} توصيف ملحق وهو يشبه إلى 'ElementName' ملزمة ولكن يحل الربط بشكل مختلف، تجاوز شجرة البصرية. وأنا أعتبر هذا أن تكون أكثر قابلية للقراءة من استخدام "PlacementTarget. هنا مثال:

<Image Source="{Binding Image}">       
    <Image.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Delete" 
                      Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"
                      CommandParameter="{Binding}" />
        </ContextMenu>
    </Image.ContextMenu>
</Image>

ووفقا للوثائق MSDN

<اقتباس فقرة>   

س: مرجع هو بناء المعرفة في XAML 2009. وفي WPF، يمكنك استخدامها   XAML ميزات عام 2009، ولكن فقط لXAML غير WPF المترجمة العلامات.   توصيف-جمعتها XAML وشكل BAML من XAML لا حاليا   دعم كلمات لغة XAML 2009 والميزات.

وأيا كان ذلك يعني ... يعمل بالنسبة لي، وإن كان.

إليك حل آخر لـ xaml فقط.(يفترض هذا أيضًا أنك تريد ما هو موجود داخل ملف DataContext, ، على سبيل المثال، أنت MVVMing هو - هي)

الخيار الأول، حيث يكون العنصر الأصلي لـ قائمة السياق ليس في DataTemplate:

Command="{Binding PlacementTarget.DataContext.MyCommand, 
         RelativeSource={RelativeSource AncestorType=ContextMenu}}"

هذا من شأنه أن يعمل على سؤال OP.لن ينجح هذا إذا كنت داخل DataTemplate.في هذه الحالات، DataContext غالبًا ما يكون واحدًا من بين العديد من المجموعة، و أنا أمر التي ترغب في الارتباط بها هي خاصية شقيقة للمجموعة داخل نفس ViewModel (ملف DataContext من النافذة، على سبيل المثال).

في هذه الحالات، يمكنك الاستفادة من بطاقة شعار لاحتجاز الوالد مؤقتًا DataContext الذي يحتوي على كل من المجموعة وICommand الخاص بك:

class ViewModel
{
    public ObservableCollection<Derp> Derps { get;set;}
    public ICommand DeleteDerp {get; set;}
} 

وفي الاكسل

<!-- ItemsSource binds to Derps in the DataContext -->
<StackPanel
    Tag="{Binding DataContext, ElementName=root}">
    <StackPanel.ContextMenu>
        <ContextMenu>
            <MenuItem
                Header="Derp"                       
                Command="{Binding PlacementTarget.Tag.DeleteDerp, 
                RelativeSource={RelativeSource 
                                    AncestorType=ContextMenu}}"
                CommandParameter="{Binding PlacementTarget.DataContext, 
                RelativeSource={RelativeSource AncestorType=ContextMenu}}">
            </MenuItem>

والقوائم السياق هي صعبة لربط ضد. وجدت خارج شجرة البصرية من التحكم الخاصة بك، وبالتالي لم يتمكنوا من العثور اسم العنصر الخاص بك.

وحاول إعداد datacontext من قائمة السياق لهدف موقعها. لديك لاستخدام RelativeSource.

<ContextMenu 
   DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> ...

وبعد تجريب بعض الشيء، اكتشفت عمل واحدة حول:

تأكد المستوى الأعلى Window / UserControl تنفيذ INameScope ووضع NameScope من ContextMenu إلى التحكم في مستوى أعلى.

public class Window1 : Window, INameScope
{
    public Window1()
    {
        InitializeComponent();
        NameScope.SetNameScope(contextMenu, this);
    }

    // Event handlers and etc...

    // Implement INameScope similar to this:
    #region INameScope Members

    Dictionary<string, object> items = new Dictionary<string, object>();

    object INameScope.FindName(string name)
    {
        return items[name];
    }

    void INameScope.RegisterName(string name, object scopedElement)
    {
        items.Add(name, scopedElement);
    }

    void INameScope.UnregisterName(string name)
    {
        items.Remove(name);
    }

    #endregion
}

وهذا يسمح قائمة السياق للعثور على العناصر المسماة داخل Window. أي خيارات أخرى؟

وأنا لست متأكدا لماذا اللجوء إلى الخدع السحرية فقط لتجنب سطر واحد من التعليمات البرمجية داخل eventhandler للالنقر بالماوس على التعامل مع بالفعل:

    private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        // this would be your tag - whatever control can be put as string intot he tag
        UIElement elm = Window.GetWindow(sender as MenuItem).FindName("whatever control") as UIElement;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top