以编程方式切换时,Switch Toggled事件将触发

时间:2017-09-14 14:01:45

标签: listview xamarin.forms xamarin.android

<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>

Model

我有上面的列表视图,有一个开关,如果labelreserved具有7的legthserved,我有一个触发器来切换开关,但我不希望只有当用户点击开关时才会触发Toggled事件。 可以做我想做的事吗?

2 个答案:

答案 0 :(得分:2)

注意: 这个解决方案对我来说是一个实验 - 所以我建议,如果你决定实现这个,请使用它谨慎。

基本上,目的是创建一个仅查看解决方案,该解决方案能够跟踪IsToggled属性的设置方式 - 无论是通过触发器,绑定上下文还是点击操作(类似于{{ 3}})

假设我们有一个仅在用户点击交换机时触发的自定义事件 - 应该解决此问题。只需在Switch添加点按识别器似乎不起作用。我们有两个选择:

  1. 创建您自己的自定义控件,提供与Switch类似的功能,但只有在捕获到点击手势时才触发切换事件 - 强烈推荐此选项。

  2. 或者,您可以使用自定义事件扩展现有Switch控件,并通过提供自己的一组可绑定属性来跟踪IsToggled属性的设置方式。

  3. 例如:

    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:将可绑定属性转换为跟踪状态而不是以前的状态。这确保了在不触发事件的情况下处理绑定更改的能力。

答案 1 :(得分:0)

您可以通过使用属性IsEnabled禁用Switch并将其设置为false来阻止用户切换交换机。