使用CommunityToolkit.Mvvm在MAUI中绑定ContextActions MenuItem。

huangapple go评论78阅读模式
英文:

Binding ContextActions MenuItem with CommunityToolkit.Mvvm in MAUI

问题

I have a problem in binding a ReplyCommand to a MenuItem in the ContextAction.

<ListView x:Name="listDictionaries" ItemsSource="{Binding Dictionaries}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <VerticalStackLayout>
                    <Label Text="{Binding Name}"
                            FontSize="18"
                            FontAttributes="Bold" />
                </VerticalStackLayout>
                <ViewCell.ContextActions>
                    <MenuItem Text="Set as default"
                       Command="{Binding Source={x:Reference listDictionaries}, Path=BindingContext.SetDefaultCommand}"
                       CommandParameter="{Binding .}" />
                </ViewCell.ContextActions>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

I associated a ViewModel to this view and in the page's code, I wrote:

DictionaryListViewModel vm;

public DictionaryList(DictionaryListViewModel model)
{
    vm = model;
    BindingContext = vm;

    InitializeComponent();
}

protected override async void OnAppearing()
{
    base.OnAppearing();

    await vm.Init();
}

The Init() method reads from the database a list of Dictionary items (Dictionary is my class, not the .NET class). In the associated ViewModel, I created this command:

[RelayCommand]
public async Task SetDefault(Dictionary dictionary)
{
    Message = "Set as default: " + SelectedDictionary.Name;
}

When I run the application, I can see a black screen, but the items are there. I can click on an item and display the value of the cell in a DisplayAlert, but the binding is not working.

If I remove the ViewCell.ContextActions, the list displays the item as expected.

What is the correct way to bind the ReplyCommand to the MenuItem?

Update

I followed the example in the Microsoft documentation, but I still have issues.

The only way I found to have this MenuItem working is to use Clicked and then in the code-behind invoke a function.

<MenuItem Text="Set as default"
    Clicked="OnSetAsDefault"
    CommandParameter="{Binding .}" />

And then in the code-behind:

public async void OnSetAsDefault(object sender, EventArgs e)
{
    var mi = ((MenuItem)sender);
    Dictionary dictionary = (Dictionary)mi.CommandParameter;
}

It is working, but at this point, I don't understand the meaning of the Command or RelayCommand.

英文:

I have a problem in binding a ReplyCommand to a MenuItem in the ContextAction.

&lt;ListView x:Name=&quot;listDictionaries&quot; ItemsSource=&quot;{Binding Dictionaries}&quot;&gt;
	&lt;ListView.ItemTemplate&gt;
		&lt;DataTemplate&gt;
			&lt;ViewCell&gt;
				&lt;VerticalStackLayout&gt;
					&lt;Label Text=&quot;{Binding Name}&quot;
							FontSize=&quot;18&quot;
							FontAttributes=&quot;Bold&quot; /&gt;
				&lt;/VerticalStackLayout&gt;
				&lt;ViewCell.ContextActions&gt;
					&lt;MenuItem Text=&quot;Set as default&quot;
					   Command=&quot;{Binding Source={x:Reference listDictionaries}, Path=BindingContext.SetDefaultCommand}&quot;
					   CommandParameter=&quot;{Binding .}&quot; /&gt;
				&lt;/ViewCell.ContextActions&gt;
			&lt;/ViewCell&gt;
		&lt;/DataTemplate&gt;
	&lt;/ListView.ItemTemplate&gt;
&lt;/ListView&gt;

I associated to this view a ViewModel and in the code of the page I wrote:

DictionaryListViewModel vm;

public DictionaryList(DictionaryListViewModel model)
{
    vm = model;
	BindingContext = vm;
    
	InitializeComponent();
}

protected override async void OnAppearing()
{
    base.OnAppearing();

    await vm.Init();
}

The Init() reads from the database a list of Dictionary items (Dictionary is my class not the NET class). In the associated ViewModel I created this command:

[RelayCommand]
public async Task SetDefault(Dictionary dictionary)
{
    Message = &quot;Set as default: &quot; + SelectedDictionary.Name;
}

When I run the application, I can see a black screen but the items are there. As you can see, I can click on one item an display the value of the cell in an DisplayAlert but the binding is not working.

使用CommunityToolkit.Mvvm在MAUI中绑定ContextActions MenuItem。

If I remove the ViewCell.ContextActions, the list displays the item as expected.

What is correct way to bind the ReplyCommand to the MenuItem?

Update

I followed the example in the Microsoft documentation but I still have issues.

The only way I found to have this MenuItem working is to use Clicked and then in the code behind invoke a function.

&lt;MenuItem Text=&quot;Set as default&quot;
			Clicked=&quot;OnSetAsDefault&quot;
		CommandParameter=&quot;{Binding .}&quot; /&gt;

and then in the code

public async void OnSetAsDefault(object sender, EventArgs e)
{
    var mi = ((MenuItem)sender);
    Dictionary dictionary = (Dictionary)mi.CommandParameter;
}

It is working but at this point I don't understand the meaning of the Command or RelayCommand.

答案1

得分: 1

我可以在Windows平台上复现你的问题。但在Android平台上它工作正常。

当你在一个需要参数的方法上使用[RelayCommand]属性时,似乎会出现一个新问题。如果你删除参数,它就会工作。比如:

[RelayCommand]
public async Task SetDefault()
{
    Message = "设为默认:";
}

你也可以像官方示例一样,使用ICommand而不是RelayCommand,它使用了**INotifyPropertyChanged接口而不是ObservableObject类**。你可以查看官方示例关于使用MVVM绑定上下文菜单项的部分。

我已经测试了使用INotifyPropertyChanged接口的ICommand而不是ObservableObjectRelayCommand,它可以正常工作。

另外,你也可以尝试在GitHub上为CommunityToolkit.Mvvm in MAUI提交一个新的问题。

英文:

I can reproduce your problem in my project on the windows platform. But it worked well in the android platfrom.

It seems a new issue when you use the [RelayCommand] attribute on a method which needs a parameter. If you delete the parameter, it will work. Such as:

[RelayCommand]
public async Task SetDefault()
{
    Message = &quot;Set as default: &quot; ;
}

And you can also use the ICommand instead of the RelayCommand just as the official sample which used the INotifyPropertyChanged interface instead of the ObservableObject class did. You can check the official sample about Binding ContextActions MenuItem with MVVM.

I have tested using ICommand of the INotifyPropertyChanged interface instead of the RealyCommand of the ObservableObject. It worked.

In addition, you can also try to post a new issue for CommunityToolkit.Mvvm in MAUI on the github.

huangapple
  • 本文由 发表于 2023年7月14日 01:23:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76681900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定