【问题标题】:Select ListViewItem when child element has focus UWP当子元素具有焦点时选择 ListViewItem UWP
【发布时间】:2016-01-03 08:57:54
【问题描述】:

我正在编写一个通用 Windows 应用程序,并且我有一个 ListView,其中 ListViewItems 包含一个 TextBox 和一个 Button。当我单击文本框时,我希望该 ListViewItem 被选中。我找到了 WPF 的解决方案,但 Style.Triggers 在 UWP 中不可用。任何人都可以指出正确的方法吗?

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:CycleStreetsUniversal.Controls"
    xmlns:common="using:CycleStreetsUniversal.Common"
    xmlns:utils="using:CycleStreetsUniversal.Utils"
    xmlns:interactivity="using:Microsoft.Xaml.Interactivity" 
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    xmlns:converters="using:CycleStreetsUniversal.Converters"
    x:Class="CycleStreetsUniversal.Pages.HomePage"
    mc:Ignorable="d" FontWeight="Light">

    <Page.Resources>
        <DataTemplate x:Key="DirectionItem">
            <Grid Padding="8,6,0,6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="50"/>
                    <ColumnDefinition Width="50"/>
                </Grid.ColumnDefinitions>
                <AutoSuggestBox x:Name="autoSuggestBox" PlaceholderText="{Binding Watermark}" QueryIcon="Find" Text="{Binding LocationName}" />    
                <Button Grid.Column="2" Visibility="{Binding ShowAddButton, Converter={StaticResource BooleanToVisibilityConverter}}" />
                <Button Grid.Column="1" Visibility="{Binding ShowMinusButton, Converter={StaticResource BooleanToVisibilityConverter}}" />
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid x:Name="Directions" HorizontalAlignment="Left" Margin="0" Width="346" DataContext="{Binding DirectionPlanner, Mode=OneWay, Source={StaticResource Locator}}">
            <Grid.Background>
                <SolidColorBrush Color="{ThemeResource SystemAltHighColor}"/>
            </Grid.Background>
            <StackPanel VerticalAlignment="Top">
                <ListView x:Name="DirectionEntryList" ItemTemplate="{StaticResource DirectionItem}" ItemsSource="{Binding Entries}">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                        </Style>
                    </ListView.ItemContainerStyle>
                </ListView>
                <Button x:Name="crosshairButton" VerticalAlignment="Top" d:LayoutOverrides="LeftPosition, RightPosition" Margin="20,0" HorizontalAlignment="Stretch" Padding="0" Click="crosshairButton_Click">
                    <Grid Height="50">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Image x:Name="image" Source="ms-appx:///Assets/crosshair.png"/>
                        <TextBlock Text="Set Location to Crosshair" Grid.Column="1" VerticalAlignment="Center" MaxLines="2" TextWrapping="Wrap"/>
                    </Grid>
                </Button>
            </StackPanel>
        </Grid>
    </Grid>
</Page>

数据模板中的AutoSuggestBox需要将DirectionEntryList中的选中项设置为AutoSuggestBox是子项的List View项。

【问题讨论】:

  • 您想使用或不使用代码隐藏吗?
  • 理想情况下可以在多个元素上重复使用——不仅仅是 AutoCompleteBox
  • 我会将 IsSelected 属性添加到项目的类并绑定到该属性并在我获得焦点或数据模板的其他事件时更改它

标签: c# xaml uwp


【解决方案1】:

解决方案背后的代码

您可以订阅AutoSuggestBoxGotFocus事件。

<AutoSuggestBox x:Name="autoSuggestBox" GotFocus="autoSuggestBox_GotFocus" />

然后,您只需要使用ListView.ContainerFromItem 方法来定位实际的ListViewItem 并将其IsSelected 属性设置为true

private void autoSuggestBox_GotFocus(object sender, RoutedEventArgs e)
{
    var item = ((AutoSuggestBox)sender).DataContext;
    var container = (ListViewItem)DirectionEntryList.ContainerFromItem(item);

    container.IsSelected = true;
}

混合友好的解决方案(无代码隐藏)

让我们通过将逻辑封装到Behavior 中来稍微改进一下这个答案。

首先,您需要从Reference Manager > Universal Windows > 添加 Behaviors SDK(XAML)(版本 12.0 atm) >扩展

那么基本上你只需要创建一个依赖属性来获取DirectionEntryList的引用,并以与后面代码完全相同的方式处理GotFocus事件。

public class SelectListViewItemWhenElementGotFocusBehavior : DependencyObject, IBehavior
{
    private UIElement _element;

    public DependencyObject AssociatedObject { get; set; }

    #region ListView reference

    public ListView ListView
    {
        get { return (ListView)GetValue(ListViewProperty); }
        set { SetValue(ListViewProperty, value); }
    }

    public static readonly DependencyProperty ListViewProperty =
        DependencyProperty.Register("ListView", typeof(ListView), typeof(SelectListViewItemWhenElementGotFocusBehavior), new PropertyMetadata(null));

    #endregion

    public void Attach(DependencyObject associatedObject)
    {
       AssociatedObject = associatedObject;
        _element = this.AssociatedObject as UIElement;

        if (_element != null)
        {
            _element.GotFocus += OnElementGotFocus;
        }
    }

    private void OnElementGotFocus(object sender, RoutedEventArgs e)
    {
        var item = ((AutoSuggestBox)sender).DataContext;
        var container = (ListViewItem)ListView.ContainerFromItem(item);

        container.IsSelected = true;
    }

    public void Detach()
    {
        if (_element != null)
        {
            _element.GotFocus += OnElementGotFocus;
        }
    }
}

要使用它,只需打开 Blend,转到 DataTemplate 并将其附加到您的 AutoSuggestBox

<AutoSuggestBox x:Name="autoSuggestBox">
    <Interactivity:Interaction.Behaviors>
        <local:SelectListViewItemWhenElementGotFocusBehavior ListView="{Binding ElementName=DirectionEntryList}" />
    </Interactivity:Interaction.Behaviors>
</AutoSuggestBox>

【讨论】:

  • 热爱你的工作。使用混合溶液。像魅力一样工作:)
  • @JustinXL 嗨,很好的解决方案 (BLEND),但在我的情况下,我有一个按钮,它“正常”工作,除了因为 private void OnElementGotFocus(object sender, RoutedEventArgs e) 一键运行多次,也许我认为,因为 Listview GotFocus 调用 Button GotFocus 创建了一个循环。我该怎么做才能解决它?
  • 谢谢!我在 ListViewItem 中有一个按钮,但使用 Clicked 有效。
【解决方案2】:

当我单击文本框时,我希望 ListViewItem 被选中。我找到了 WPF 的解决方案,但 Style.Triggers 在 UWP 中不可用。

在 UWP 中,您可以使用 ViewState.Setters 设置样式,并通过 GotFocus 和 LostFocus 事件触发状态更改。

例如:

<Page
    x:Class="UWPApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid 
        x:Name="container"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="ValueStates">
                <VisualState x:Name="Selected">
                    <VisualState.Setters>
                        <Setter Target="button.Background" Value="Red"></Setter>
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="UnSelected">
                    <VisualState.Setters>
                        <Setter Target="button.Background" Value="Blue"></Setter>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <StackPanel>
            <TextBox x:Name="inputbox" GotFocus="inputbox_GotFocus" LostFocus="inputbox_LostFocus"></TextBox>
            <Button x:Name="button">Click Me</Button>
        </StackPanel>
    </Grid>
</Page>

C#代码:

private void inputbox_GotFocus(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    VisualStateManager.GoToState(this, "Selected", false);
}

private void inputbox_LostFocus(object sender, RoutedEventArgs e)
{
    VisualStateManager.GoToState(this, "UnSelected", false);
}

【讨论】:

  • 我添加了一个精简版的布局代码来显示我的设置。数据模板中的 AutoSuggestBox 需要将 DirectionEntryList 中的选中项设置为 AutoSuggestBox 是子项的 List View 项。我不确定如何使用您建议的代码来解决此问题。
猜你喜欢
  • 2012-02-27
  • 2020-07-25
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
相关资源
最近更新 更多