<StackLayout BackgroundColor="White">
<ListView x:Name="ListViewMenu" ItemsSource="{Binding Menus}"
HasUnevenRows="True"
BackgroundColor="White"
SeparatorVisibility="None"
VerticalOptions="FillAndExpand"
ItemTapped="Handle_ItemTapped"
ItemSelected="Handle_ItemSelected"
IsGroupingEnabled = "true"
SeparatorColor="White">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout BackgroundColor="LightSkyBlue" HeightRequest="25">
<Label Text="{Binding Key}" FontAttributes="Bold" LineBreakMode="NoWrap" Margin="10,0,0,0">
</Label>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Text="{Binding article_description}"
FontAttributes="Bold" FontSize="13" Margin="10,5,0,-6" Grid.Row="0" LineBreakMode="NoWrap"/>
<Label Text="{Binding dish_name}"
FontSize="13" Margin="10,0,0,2" Grid.Row="1" Grid.Column="0"/>
<Label Grid.Row="0" Grid.Column="0" x:Name="LabelReserved" Text="{Binding reserved}" IsVisible="false" LineBreakMode="NoWrap"/>
<Switch Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" IsEnabled="False" Toggled="SwitchMenu_OnToggled" >
<Switch.Triggers>
<DataTrigger TargetType="Switch" Binding="{Binding Source={x:Reference LabelReserved},
Path=Text.Length}" Value="7">
<Setter Property="IsToggled" Value="true" />
</DataTrigger>
</Switch.Triggers>
</Switch>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
我上面有一个列表视图,它有一个开关,如果 labelreserved 的长度为 7,我有一个触发器来切换开关,但我不希望只有当用户单击开关时才触发 Toggled 事件。 可以做我想做的事吗?
注意: 这个解决方案是我的一个实验 - 所以我建议,如果你决定实现这个,请谨慎使用。
基本上,目的是创建一个仅查看的解决方案,能够跟踪如何设置
IsToggled
属性 - 无论是通过触发器、绑定上下文还是点击操作(类似于维护的 属性上下文)对于 BindingContext
于 BindableObject
)
假设我们有一个自定义事件,仅当用户点击开关时才会触发 - 这个问题应该得到解决。简单地向
Switch
添加点击识别器似乎不起作用。我们只剩下两个选择:
创建您自己的自定义控件,提供与
Switch
类似的功能,但仅在捕获点击手势时触发切换事件 - 强烈推荐此选项。 或者,您可以使用自定义事件扩展现有
Switch
控件,并通过提供其自己的一组可绑定属性来跟踪 IsToggled
属性的设置方式。 例如:
public class CustomSwitch : Switch
{
internal enum ToggledSetFlags
{
None = 0,
FromCode = 1 << 0,
}
ToggledSetFlags _toggleSetStatus = ToggledSetFlags.None;
public event EventHandler<ToggledEventArgs> UserToggled;
public static readonly BindableProperty ToggledStateFromCodeProperty =
BindableProperty.Create(
"ToggledStateFromCode", typeof(bool), typeof(CustomSwitch),
defaultBindingMode: BindingMode.TwoWay,
defaultValue: default(bool), propertyChanged: OnToggledStateFromCodeChanged);
public bool ToggledStateFromCode
{
get { return (bool)GetValue(ToggledStateFromCodeProperty); }
set { SetValue(ToggledStateFromCodeProperty, value); }
}
private static void OnToggledStateFromCodeChanged(BindableObject bindable, object oldValue, object newValue)
{
((CustomSwitch)bindable).OnToggledStateFromCodeChangedImpl((bool)oldValue, (bool)newValue);
}
protected virtual void OnToggledStateFromCodeChangedImpl(bool oldValue, bool newValue)
{
if (ToggledStateFromCode != IsToggled)
{
_toggleSetStatus = ToggledSetFlags.FromCode;
IsToggled = ToggledStateFromCode;
}
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == nameof(IsToggled))
{
ToggledStateFromCode = IsToggled;
if (_toggleSetStatus == ToggledSetFlags.None)
UserToggled?.Invoke(this, new ToggledEventArgs(IsToggled));
else
_toggleSetStatus = ToggledSetFlags.None;
}
}
}
并且,示例用法如下所示:
<local:CustomSwitch
Grid.Row="0" Grid.RowSpan="2" Grid.Column="1"
HorizontalOptions="Start" VerticalOptions="Center"
ToggledStateFromCode="{Binding IsSwitchOn}"
UserToggled="SwitchMenu_OnToggled">
<Switch.Triggers>
<DataTrigger TargetType="{x:Type local:CustomSwitch}"
Binding="{Binding Source={x:Reference LabelReserved},
Path=Text.Length}" Value="7">
<Setter Property="ToggledStateFromCode" Value="true" />
</DataTrigger>
</Switch.Triggers>
</local:CustomSwitch>
编辑1:在恢复自定义切换属性状态时错过了在
else
方法中添加OnPropertyChanged
。此外,仅在当前切换值不同时添加检查以设置标志。
编辑2: 将可绑定属性转换为跟踪状态,而不是像以前一样无状态。这确保了能够在不触发事件的情况下处理绑定更改。
您可以通过使用属性
IsEnabled
禁用 Switch 并将其设置为 false 来防止用户切换开关。
这个问题很旧,但我找到了一个简单(有点不正确)的解决方案,我用它来从已接受的答案中节省大量额外的工作。 当我以编程方式切换开关时,我将 Tag 属性设置为 true。
ToggleSwitch.Tag = true;
ToggleSwitch.IsOn = true (or false);
然后在我的 Toggled 事件中,我检查 Tag 属性是否为 null 并执行我的操作。这样,事件被触发的唯一时间就是用户切换开关时。
private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{
ToggleSwitch toggleSwitch = (ToggleSwitch)e.OriginalSource;
if (toggleSwitch.Tag == null)
{
// Switch was toggled by user, do some action.
}
else
{
// Switch was toggled programmatically, set Tag null.
toggleSwitch.Tag = null;
}
}