-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MenuItem: CommandParameters are ignored #4078
Comments
Your (Edit: You can see what I mean if you change your Try this instead:
|
This is strange ... According to the book "Pro WPF 4.0 in C#" from Apress and Microsoft docs this should work: <!-- In MainWindow.xaml -->
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_Exit"
Command="{Binding Path=CloseCommand}" />
</MenuItem>
<MenuItem Header="_Edit" />
<MenuItem Header="_Options" />
<MenuItem Header="_Help" />
</Menu> In both examples, the outer |
I think it's slowly getting in my grasp ... So you suggest, the structure created from my original code is like this: <Menu DockPanel.Dock="Top">
<MenuItem Header="Film_liste" ItemsSource="{Binding Path=Commands}">
<MenuItem>
<MenuItem Command="{Binding}" CommandParameter="{Binding ElementName=Filmliste, Path=SelectedItem}" Header="{Binding Path=Text}" /> ... because a menu item's item container is a menu item itself? Shouldn't this layout practically be presented in the Visual Live Tree? It doesn't seem to be like this: After changing the menu layout according to your (correct) suggestion, I just noticed another glitch: When any of the films get selected for the first time after program start, while the "Remove Film" |
No, I was suggesting your code was putting Your book example, on the other hand, is creating submenus, i.e. populating the |
Changes implemented according to discussion at dotnet/wpf#4078
Did you read my second comment? |
I believe I have evidence that there's a bug in the way commands in
In my example project, I can reliably reproduce the erroneous behaviour:When you ...
... the When, however, you ...
... binding is getting performed correctly. Here's the flow chart, reporting the two approaches:Here's a screencast, reporting a debug session performing the successful path:And here's a screencast, reporting a debug session performing the error path:In case anyone needs to manually pause/rewind, here's the original screencast recording:MenuItem.doesn.t.convey.CommandParameter.-.2.mp4 |
Because this thread has grown old an possibly out of sight, I'd like to invite @ryalanms to this bug report. |
Then this seems to be a duplicate of #3452. (changing command parameter does not actually re-evaluate CanExecute) |
Are you sure? After reading the other issue I don't think so, because:
So, in my case the Plus, in contrast to the other case, in my case the issue seems to only exist for |
I suppose, someone with sufficient Member's/Contributor's expertise, equipped with a debug build from WPF Core should smoothly be able to find and fix the command parameter binding issue I reported by debugging into the WPF framework function that's calling I provided all that's necessary to reproduce the issue: A minimum MVVM WPF project and detailed steps for how to reproduce. |
I'm sorry you are stuck with me. I am pretty sure, you can see yourself by setting the command parameter first: Change <Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding}" />
<Setter Property="CommandParameter" Value="{Binding ElementName=Filmliste, Path=SelectedItem}" />
<Setter Property="Header" Value="{Binding Path=Text}" />
</Style> to <Style TargetType="MenuItem">
<Setter Property="CommandParameter" Value="{Binding ElementName=Filmliste, Path=SelectedItem}" />
<Setter Property="Command" Value="{Binding}" />
<Setter Property="Header" Value="{Binding Path=Text}" />
</Style> |
Sincerely pardon me, @miloush, no insulting intended when I wrote my previous comment. I'm sorry if it inadvertently caused irritation on your behalf. After reading your comment, I found the following blogs about this issue: I don't think, this exotic behaviour is documented. I can't find any documentation on this. On the contrary - the following is the current state of WPF attribute sequence documentation I'm aware of: Matthew MacDonald, "Pro WPF 4.5 in C#", 4th edition, ApressPage 102, "The Coercion Callback"
Microsoft Docs, "Coerce Value Callbacks and Property Changed Events"
Microsoft Docs, "DependsOnAttribute Class"
However: Microsoft Docs, "MenuItem.CommandParameter Property"[System.ComponentModel.Bindable(true)]
[System.Windows.Localizability(System.Windows.LocalizationCategory.NeverLocalize)]
public object CommandParameter { get; set; } If this behaviour is not documented ...
I can test and implement your suggested workaround. Then I will have a local solution and have learned from life. - However, shouldn't this be fixed in WPF, once and for all, so programmers around the globe won't repeatedly stumble over this irritating and undocumented behaviour? On the other hand: if there's a requirement preventing to fix this, shouldn't Visual Studio render a warning message if these attributes weren't given in correct sequence? Why does it work with the |
So what happens is that when you open the menu for the first time, the MenuItems get created - the constructor is called, and all the properties are set in the order that it is specified in XAML. That way the See the Note that at this point, the Now the loader sets (bounds) the Now when you are done loading, both
I don't see such guarantee in the documentation, and there are other types where the order matters (e.g. whether you set first I do agree, however, that pretending that |
Shouldn't this line in if ((owner != null) && ((owner is MenuItem) || (owner is MenuBase)))
{
// Parent must be MenuItem or MenuBase in order for menus to open.
// Otherwise, odd behavior will occur.
SetCurrentValueInternal(IsSubmenuOpenProperty, BooleanBoxes.TrueBox);
return true; // The value was actually changed
} ... be rather amended by subsequently iterating through the if ((owner != null) && ((owner is MenuItem) || (owner is MenuBase)))
{
// Parent must be MenuItem or MenuBase in order for menus to open.
// Otherwise, odd behavior will occur.
SetCurrentValueInternal(IsSubmenuOpenProperty, BooleanBoxes.TrueBox);
foreach (MenuItem mi in Children) mi.UpdateCanExecute();
return true; // The value was actually changed
} Wouldn't that make sense? |
#316 - this is the issue I was looking for |
We've been writing in parallel. Did you read my last comment? I'll be reading your references now. |
I don't think you should invalidate all |
I believe you need to. Because only at the moment when a menu opens you get the current program state, particularly when the And, yes, this issue very much resembles #316. But that seems to have been fixed. I'm using the |
What scenario do you have in mind where calling |
Ah, OK, I see. Right ... The issue comes in when So, is it possible to bind an event handler to call |
Something similar to (I'm writing a coarse idea here): [CommonDependencyProperty]
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register( "CommandParameter", typeof(object), typeof(...), new FrameworkPropertyMetadata((object) null),
param => switch (param)
{
case Binding b:
b.TargetUpdated +=new EventHandler<DataTransferEventArgs>(delegate (depObj obj, DataTransferEventArgs args) => UpdateCanExecute();)
}
); |
Yes, that's exactly what #3452 is asking for. Sorry I didn't make it clear, the property changed callback is called anytime the value is changed, which can come from binding source value change, style trigger change, direct value assignment etc., (i.e. it does not only mean "assigning a binding to it") This is how it's done with the You want the same with |
Ahh ... now I get it! Perfect. So, I voted for that issue now. Shall we close this issue here then? Or keep it open for documentation reasons? You've been great, very helpful, thorough, thoughtful. Thanks so much for your patience and spending your time in enlightening me and following my concerns! |
You're welcome, sorry for the delays in responding. I think you can close this issue (as duplicate of #316), it will stay available for documentation purposes. |
Sure, go ahead! |
See this GitHub issue: dotnet/wpf#4078 (comment)
Problem description:
I created an MVVM sample repository. In this repository I'm loading
MenuItem
s andButton
s with commands.While the
Button
elements callICommand::Execute(object? parameter)
with the givenCommandParameter
,MenuItem
elements don't.Here's a code snipped showing both declarations:
Actual behavior:
Commands triggered by
MenuItem
elements are always passednull
as command parameter.Expected behavior:
Commands triggered by
MenuItem
elements should be passed the value provided as command parameter.Minimal repro:
MVVM Test repository
Steps to reproduce:
MenuItem.doesn.t.convey.CommandParameter.mp4
The text was updated successfully, but these errors were encountered: