简体   繁体   中英

Execute the Command in Listview MenuItem MVVM

Why does the Command in my Listview Menu Item is not executing?

This is the code on my Listview

<ListView ItemsSource="{Binding ListDataCorrection}"  >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Validate">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Button Content="Update" Margin="5" Cursor="Hand" Command="{Binding RelativeSource={RelativeSource FindAncestor, 
                                        AncestorType={x:Type ListView}}, Path=DataContext.ValidateCommand}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>

            <ListView.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Remove" Command="{Binding RelativeSource={RelativeSource FindAncestor, 
                                        AncestorType={x:Type ListView}}, Path=DataContext.ValidateAllCommand}">
                    </MenuItem>
                </ContextMenu>
            </ListView.ContextMenu>
        </ListView>

But the weird thing is the ValidateCommand inside the Gridview is executed.

While the Command in the MenuItem is not.

What's is wrong with my Binding?

And i also checked if the Command name is correct. If not i should receive an error saying that the command is not found in the ViewModel

Thank you.

I'm having this problem too sometimes with MenuItems inside a ContextMenu . I guess that the ContextMenu can't find the correct DataContext.

My soltuion for this is a BindingProxy-class which looks like:

public class BindingProxy : Freezable
{   
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
        "Data", typeof (object), typeof (BindingProxy), new UIPropertyMetadata(null));

    /// <summary>
    ///     This Property holds the DataContext
    /// </summary>
    public object Data
    {
        get { return GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }
}

In the resources of your view (UserControl or Window) you have to add the proxy like:

<codeBase:BindingProxy x:Key="proxy" Data="{Binding}"/>

And in your MenuItem you can use it with:

<MenuItem Header="Remove" Command="{Binding Source={StaticResource proxy}, Path=Data.ValidateAllCommand}"/>

A Menu (as well as a Popup for example) is not part of the visual-tree, as it is created on demand. Since its is not part of the visual-tree, it will not inherit its parents DataContext. However you can still bind to your ListView using the PlacementTarget -property in your binding:

        <ListView.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Remove" 
                          Command="{Binding Path=PlacementTarget.DataContext.ValidateAllCommand}">
                </MenuItem>
            </ContextMenu>
        </ListView.ContextMenu>

Why does the Command in my Listview Menu Item is not executing?

Because the ListView is not a visual ancestor of the MenuItem so the RelativeSource of the binding isn't found.

If you change the AncestorType to ContextMenu and bind to its PlacementTarget , it should work:

<ContextMenu>
    <MenuItem Header="Remove" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, 
                    Path=PlacementTarget.DataContext.ValidateAllCommand}">
    </MenuItem>
</ContextMenu>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM