本文介绍了Xamarin Forms Switch Toggled 事件未与视图模型绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Forms XAML 页面,其中有一个列表视图,每个元素都有一个 Switch(xamarin 默认).我可以将项目中的数据绑定到列表视图,但我无法订阅 Switch 事件Toggled",因为它会导致项目不显示.我也尝试过 ICommand 和 Command,因为它被指示使用按钮,但结果是一样的,没有显示.如何处理我的视图模型中的开关切换?

I have a Forms XAML Page and in there I have a listview, and each element has a Switch (xamarin default). I can bind the data from the items to the listview, but I cannot subscrive the Switch event "Toggled", as it causes the item not to show. I also tried with ICommand and Command, as it is instructed to do with buttons, but the result is the same, nothing shown. How can I handle the switch toggle from the my viewmodel?

    <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TouristicWallet.Views.WalletManagementPage"
             xmlns:vm="clr-namespace:TouristicWallet.ViewModels"
             xmlns:converters="clr-namespace:TouristicWallet.Converters"
             >

  <ContentPage.BindingContext>
    <vm:WalletManagementViewModel x:Name="ViewModel"/>
  </ContentPage.BindingContext>

  <ContentPage.Resources>
    <ResourceDictionary>
      <converters:CurrencyIdToCodeConverter x:Key="idToCodeConverter"/>
    </ResourceDictionary>
  </ContentPage.Resources>

  <StackLayout>
    <ListView x:Name="MyCurrencies" ItemsSource="{Binding Currencies, Mode=OneWay}">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <StackLayout Orientation="Horizontal">
              <Label Text="{Binding Currency.Initials, Mode=OneWay}" />
              <Switch IsToggled="{Binding IsOwned, Mode=TwoWay}"
                      Toggled="{Binding Toggled}"
                      />
            </StackLayout>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

  </StackLayout>
</ContentPage>

视图模型

public class WalletManagementViewModel : ViewModelBase
{

    private readonly List<OwnedCurrencyWrapper> _currencies = new List<OwnedCurrencyWrapper>();
    public List<OwnedCurrencyWrapper> Currencies { get { return _currencies; } }

    public WalletManagementViewModel()
    {
        CurrencyDataAccess cda = new CurrencyDataAccess();
        foreach (var item in cda.GetCurrencies())
        {
            Currencies.Add(new OwnedCurrencyWrapper(item));
        }

        OnPropertyChanged(nameof(Currencies));
    }

    public class OwnedCurrencyWrapper
    {
        public Currency Currency { get; private set; }
        public Boolean IsOwned { get; set; }
        public ICommand Toggled { get; set; }


        public OwnedCurrencyWrapper(Currency currency)
        {
            Currency = currency;
            WalletDataAccess wda = WalletDataAccess.Instance;
            IsOwned = wda.IsOwned(Currency.Id);

            Toggled = new Command(() => Update());
        }

        public void Update()
        {
            WalletDataAccess wda = WalletDataAccess.Instance;
            if (IsOwned) wda.RemoveOwnedCurrency(Currency.Id);
            else wda.OwnCurrency(Currency.Id);

        }

        public void Toggled_handler(object sender, ToggledEventArgs e)
        {
            Update();
        }
    }
}

我没有使用任何 mvvm 框架

I am not using any mvvm framework

推荐答案

首先,Switch 无法绑定到 Command.看:https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/#Commanding_with_ViewModels

First off a Switch can not bind to a Command. See:https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/#Commanding_with_ViewModels

从上面可以绑定到 ICommand 的 Forms 控件是:

From the above, the Forms controls that can bind to an ICommand are:

  • 按钮
  • 菜单项
  • 工具栏项
  • 搜索栏
  • TextCell(因此也图像单元)
  • 列表视图
  • TapGestureRecognizer

您只需执行以下操作即可在视图的代码隐藏文件中运行代码,在 XAML 中执行此操作:

you can just do the following to run code in the View's code behind file, do this in the XAML:

<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}"
        Toggled="Handle_Toggled" />

然后在代码隐藏文件中:

And then in the Code behind file:

void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
{
    // Do stuff
}

或者,由于您正在绑定,您可以在实际的 OwnedCurrencyWrapper 类中运行代码(这似乎是您想要的),只需将代码添加到 IsOwned.在这种情况下,不要为您的开关的 Toggled 属性分配任何内容::

Alternately, since you are binding, you could run code in the actual OwnedCurrencyWrapper class (which is what you seem to want) just by adding code to the setter for IsOwned. IN this case, don't assign anything to the Toggled property of your switch::

<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}" />

然后在您的 OwnedCurrencyWrapper 类中:

bool _isOwned;
public bool IsOwned {
    get
    {
        return _isOwned;
    }
    set
    {
        _isOwned = value;
        // Do any other stuff you want here
    }
}

也就是说,您的绑定不完整,因为您的视图模型没有实现 INotifyPropertyChanged,因此直接对视图模型所做的更改不会反映在 UI 中.有关与 Forms MVVM 绑定的更多信息,请参阅:https://developer.xamarin.com/guides/xamarin-表单/xaml/xaml-basics/data_bindings_to_mvvm/

That said, your binding is not complete since your view model is not implementing INotifyPropertyChanged so changes made directly to the view model will not be reflected in the UI. For more info on binding with Forms MVVM, see:https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/

更新:我不知道 Xamarin 表单中的行为.看:https://github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior

UPDATE: I was not aware of Behaviors in Xamarin Forms. See:https://github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior

在命令上下文中,行为是将控件连接到命令的有用方法.此外,它们还可用于将命令与未设计为与命令交互的控件相关联.此示例演示了如何在事件触发时使用行为来调用命令.

所以这应该允许您将 Toggled 事件绑定到命令.

So this should allow you to bind the Toggled event to a Command.

这篇关于Xamarin Forms Switch Toggled 事件未与视图模型绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 04:45