我有一个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>
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框架
答案 0 :(得分:12)
首先关闭Switch无法绑定到Command
。看到:
https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/#Commanding_with_ViewModels
从上面可以看出,可绑定到ICommand
的Forms控件是:
您只需执行以下操作即可在View后面的代码中运行代码,在XAML中执行此操作:
<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}"
Toggled="Handle_Toggled" />
然后在Code后面的文件中:
void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
{
// Do stuff
}
或者,由于您是绑定的,只需在OwnedCurrencyWrapper
的setter中添加代码,就可以在实际的IsOwned
类中运行代码(这就是您想要的)。在这种情况下,不要为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-forms/xaml/xaml-basics/data_bindings_to_mvvm/
更新:我不知道Xamarin表格中的行为。看到: https://github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior
在命令的上下文中,行为是将控件连接到命令的有用方法。此外,它们还可用于将命令与未设计为与命令交互的控件相关联。此示例演示了在事件触发时使用行为来调用命令。
因此,这应该允许您将Toggled事件绑定到Command。
答案 1 :(得分:5)
正如其他人所提到的,您应该将Toggled事件绑定到将转发命令的eventHandler行为。可以使用以下代码。
filename = open("output3.txt")
f = open("countoutput.txt", "w")
import collections
for line in filename:
for number in line.split():
print(collections.Counter("f"))
break
答案 2 :(得分:3)
如果您遵循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>
答案 3 :(得分:0)
解决方案:经过一些研发,我发现了此问题的根本原因,
第一篇文章中的错误代码:
<Switch IsToggled="{Binding IsOwned, Mode=TwoWay}"
Toggled="{Binding Toggled}"
/>
只需执行两个步骤。
在您的 ContentPage 类中
void OnToggled(object sender, ToggledEventArgs e){
}
将 Toggled =“ {Binding Toggled}” ==更改为==> Toggled =“ OnToggled”
它将解决此问题,不知道为什么它不适用于ViweModel类中声明的事件侦听器功能。
-我希望它能起作用。
答案 4 :(得分:0)
我遇到了同样的问题,并以非常简单的方式解决了它。
=> 目标:在列表视图中使用开关控件获取项目以响应命令。
<?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"
x:Name="pageName"
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 Selected}" HorizontalOptions="Start">
<Switch.Behaviors>
<b:EventToCommandBehavior
EventName="Toggled" Command="
{Binding
Path=BindingContext.SendCommand,
Source={x:Reference
Name=pageName}}" />
</Switch.Behaviors>
</Switch>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
在视图模型中 定义你的命令 /ICommand
public ICommand SendCommand { get; set; }
SendCommand = new Command(() => //do something.....);
请特别注意粗体部分。