如何在Xaml & Maui的ContentView中使用VisualStateManager?

zvms9eto  于 2023-03-16  发布在  其他
关注(0)|答案(1)|浏览(207)

我在整个应用中多次使用特定的Border控件。此Border控件显示为CollectionView的一部分。在CollectionView中选择Border及其包含的项目时,我使用VisualStateManager控制Border颜色。以下是定义Border控件的位置:

<CollectionView Margin="0,10,0,0" ItemsLayout="HorizontalList" HorizontalOptions="Center"
                        ItemsSource="{Binding Source={x:Static vm:WaxItVM.SnowSourceButtons}}"
                        SelectionMode="Single" SelectedItem="{Binding SelectedSnowSourceButton}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Border StrokeShape="RoundRectangle 10" StrokeThickness="2" Margin="4,0,4,0">
                        <Image Source="{Binding IconFileName}" Margin="6,6,6,6" WidthRequest="35" HeightRequest="35" VerticalOptions="Center" HorizontalOptions="Center">
                            <Image.Behaviors>
                                <mct:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black},Dark={StaticResource White}}"/>
                            </Image.Behaviors>
                        </Image>
                    </Border>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

下面是我如何在同一个ContentPage文件中使用VisualStateManager:

<ContentPage.Resources>
        <Style TargetType="Border">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="Stroke" Value="{StaticResource Primary}" />
                                <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White},Dark={StaticResource Black}}" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>
    </ContentPage.Resources>

然后我决定将Border控件提取到一个名为SnowConditionInputButton.xaml的包含ContentView的单独Xaml文件中。

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="FasterWaxer.CustomComponents.SnowConditionInputButton">
    
    <Border StrokeShape="RoundRectangle 10" StrokeThickness="2" Margin="4,0,4,0">
        <Image Source="{Binding IconFileName}" Margin="6,6,6,6" WidthRequest="35" HeightRequest="35" VerticalOptions="Center" HorizontalOptions="Center">
            <Image.Behaviors>
                <mct:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black},Dark={StaticResource White}}"/>
            </Image.Behaviors>
        </Image>
    </Border>
    
</ContentView>

然后我将我的内容页更改为:

<CollectionView Margin="0,10,0,0" ItemsLayout="HorizontalList" HorizontalOptions="Center"
                        ItemsSource="{Binding Source={x:Static vm:WaxItVM.SnowSourceButtons}}"
                        SelectionMode="Single" SelectedItem="{Binding SelectedSnowSourceButton}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <custom_components:SnowConditionInputButton/>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

当我这样做时,每个CollectionView项都正确显示,但当我选择CollectionView项时,Border颜色不再更改。当我将ContentPage.Resources移到单独的ContentView时,它似乎不再应用于Border控件。因此,我尝试将VisualStateManager移到ContentView以显式控制Border颜色。当这样做时,边框仍然不响应在CollectionView中被选择:

<Border StrokeShape="RoundRectangle 10" StrokeThickness="2" Margin="4,0,4,0">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter Property="Stroke" Value="{StaticResource Primary}" />
                            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White},Dark={StaticResource Black}}" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </VisualStateManager.VisualStateGroups>
        <Image Source="{Binding IconFileName}" Margin="6,6,6,6" WidthRequest="35" HeightRequest="35" VerticalOptions="Center" HorizontalOptions="Center">
            <Image.Behaviors>
                <mct:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black},Dark={StaticResource White}}"/>
            </Image.Behaviors>
        </Image>
    </Border>

如何将该Border控件和相关的VisualStateManager提取到一个单独的Xaml文件中以供重用?顺便说一句,我不希望该Border配置应用于整个应用中的所有边框,因此我不希望将其定义为应用于所有边框的全局边框样式。我希望有选择地将其应用于特定边框或页面上的所有边框。
谢谢你的帮助。

ubof19bj

ubof19bj1#

您可以对代码进行一些更改:
首先,在ContentView中,为Border命名,我们将其命名为myBorder,它将在VisualStateManger中引用。

<ContentView  xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         ...>

    <Border  x:Name="myBorder"  StrokeShape="RoundRectangle 10" StrokeThickness="2" Margin="4,0,4,0" HeightRequest="50" >
    ...
    </Border>
</ContentView>

在ContentPage中,对VisualStateManager进行一些更改。由于VisualStateGroups附加到自定义控件SnowConditionInputButtonm,因此应将TargetName和属性设置为Border,如下所示:

<ContentPage.Resources>
    <Style  TargetType="custom_components:SnowConditionInputButton">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter TargetName="myBorder" Property="Border.Stroke" Value="{StaticResource Primary}" />
                            <Setter TargetName="myBorder" Property="Border.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White},Dark={StaticResource Black}}" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>
</ContentPage.Resources>

然后在CollectionView中轻松使用自定义控件:

<CollectionView.ItemTemplate>
    <DataTemplate>
        <custom_components:SnowConditionInputButton/>    
    </DataTemplate>
</CollectionView.ItemTemplate>

如果你不想像上面的代码那样使用Style,你可以很容易地在SnowConditionInputButton中定义VisualStateManager。

<custom_components:SnowConditionInputButton HeightRequest="100">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroupList>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal" />
                <VisualState x:Name="Selected">
                    <VisualState.Setters>
                        <Setter TargetName="myBorder" Property="Border.Stroke" Value="{StaticResource Primary}" />
                        <Setter TargetName="myBorder" Property="Border.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White},Dark={StaticResource Black}}" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>
    </VisualStateManager.VisualStateGroups>
</custom_components:SnowConditionInputButton>

希望对你有用。

相关问题