Select ListViewItem when child element has focus UWP
Select ListViewItem when child element has focus UWP
我正在编写一个通用 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 子项的列表视图项。
When I click in the text box I would like that ListViewItem to become selected. I've found solutions for WPF but Style.Triggers isn't available in 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
的 GotFocus
活动。
<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 添加 Behaviors SDK(XAML)(版本 12.0 atm)> 通用 Windows > 扩展.
然后基本上你只需要创建一个依赖项 属性 来获取 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>
我正在编写一个通用 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 子项的列表视图项。
When I click in the text box I would like that ListViewItem to become selected. I've found solutions for WPF but Style.Triggers isn't available in 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
的 GotFocus
活动。
<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 添加 Behaviors SDK(XAML)(版本 12.0 atm)> 通用 Windows > 扩展.
然后基本上你只需要创建一个依赖项 属性 来获取 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>