Xamarin Forms Switch Toggled事件不与viewmodel绑定

Dan*_*nça 6 mvvm xamarin xamarin.forms

我有一个Forms XAML页面,在那里我有一个listview,每个元素都有一个Switch(默认为xamarin).我可以将项目中的数据绑定到listview,但我无法订阅Switch事件"Toggled",因为它会导致项目不显示.我也尝试使用ICommand和Command,因为它被指示用于按钮,但结果是相同的,没有显示.如何从我的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>
Run Code Online (Sandbox Code Playgroud)

视图模型

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有使用任何mvvm框架

jgo*_*SFT 12

首先关闭Switch无法绑定到Command.请参阅:https: //developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/#Commanding_with_ViewModels

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

  • 按键
  • 菜单项
  • ToolbarItem
  • 搜索栏
  • TextCell(因此也是ImageCell)
  • 列表显示
  • TapGestureRecognizer

您可以执行以下操作以在View的代码隐藏文件中运行代码,在XAML中执行此操作:

<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}"
        Toggled="Handle_Toggled" />
Run Code Online (Sandbox Code Playgroud)

然后在Code后面的文件中:

void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
{
    // Do stuff
}
Run Code Online (Sandbox Code Playgroud)

或者,既然你是绑定的,那么OwnedCurrencyWrapper只需在setter中添加代码,就可以在实际的类中运行代码(这就是你想要的)IsOwned.在这种情况下,不要将任何内容分配给switch的Toggled属性::

<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}" />
Run Code Online (Sandbox Code Playgroud)

然后在你的OwnedCurrencyWrapper班上:

bool _isOwned;
public bool IsOwned { 
    get 
    {
        return _isOwned;
    } 
    set
    {
        _isOwned = value;
        // Do any other stuff you want here
    }
}
Run Code Online (Sandbox Code Playgroud)

也就是说,由于您的视图模型未实现,INotifyPropertyChanged因此绑定未完成,因此直接对视图模型进行的更改将不会反映在UI中.有关与Forms MVVM绑定的更多信息,请参阅:https: //developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/

更新:我不知道Xamarin Forms中的行为.请参阅:https: //github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior

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

因此,这应该允许您将Toggled事件绑定到Command.

  • 这是另一个选项,行为:https://github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior"行为是将控件连接到命令的有用方法.此外,它们还可以用于将命令与未设计为与命令交互的控件相关联.此示例演示了在事件触发时使用行为来调用命令.我以前不知道行为,抱歉. (2认同)

Mir*_*tei 6

如果您遵循Prism框架,则可以轻松地将事件连接到命令。您的xaml如下例所示。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                 xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
                 x:Class="TouristicWallet.Views.WalletManagementPage">
    <ContentPage.Content>
        <StackLayout VerticalOptions="CenterAndExpand" Padding="20">
            <Switch IsToggled="{Binding IsOwned}"  x:Name="IsOwnedSwitch">
                <Switch.Behaviors>
                    <b:EventToCommandBehavior EventName="Toggled"  Command="{Binding ToggleIsOwnedCommand}"/>
                </Switch.Behaviors>
            </Switch>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
Run Code Online (Sandbox Code Playgroud)


lyn*_*hey 5

正如其他人提到的那样,您应该将Toggled事件绑定到eventHandler行为,该行为将转发命令。可以使用下面的代码。

<Switch IsToggled="{Binding SwitchEnabled}"  x:Name="MySwitch">
    <Switch.Behaviors>
    <!-- behaviors namespace comes from "Xamarin.Forms Behaviors" nuget  -->
        <behaviors:EventHandlerBehavior EventName="Toggled">
            <behaviors:InvokeCommandAction Command="{Binding ToggleSwitchCommand}" />
        </behaviors:EventHandlerBehavior>
    </Switch.Behaviors>
</Switch>
Run Code Online (Sandbox Code Playgroud)