c# - 如何将放置在拆分按钮内容内的标签文本与选定的列表框项目绑定?
问题描述
我正在尝试使用 WPF 拆分按钮创建一个类似控件的下拉菜单。我可以让下拉菜单工作,但我接下来要实现的是,如果用户从下拉菜单中选择一个项目,该文本将更新为拆分按钮内容。此外,默认情况下,加载此控件时,第一个项目名称设置为拆分按钮内容。
我的偏好是在 xaml 本身中进行。
这是现有代码:
<userControls:BaseUserControl x:Class="UserControls.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:userControls="clr-namespace:MainAssembly.UserControls"
xmlns:const="clr-namespace:MainAssembly.const"
xmlns:toolkit="abc/Wpf.Toolkit"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<userControls:BaseUserControl.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<toolkit:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<toolkit:MultiValueToObjectArrayConverter x:Key="MultiValueToObjectArrayConverter" />
<toolkit:BoolToInvertedBoolToVisibilityConverter x:Key="BoolToInvertedBoolToVisibilityConverter" />
</ResourceDictionary>
</userControls:BaseUserControl.Resources>
<xctk:SplitButton Name="TestSplitBtn" ToolBar.OverflowMode="AsNeeded"
Margin="5,1,5,1"
>
<xctk:SplitButton.DropDownContent>
<ListBox Name="DropDownMenu" Margin="5,1,5,5"
ItemsSource="{Binding DropDownContentCollection}"
ToolBar.OverflowMode="AsNeeded"
Visibility="{Binding DropDownContentCollection, Converter={StaticResource NullToVisibilityConverter}}"
ToolTip="{x:Static const:const.toolTip}"
MaxWidth="150">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Style="{DynamicResource TransparentButton}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Command="{Binding DataContext.TestCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}}" CommandParameter="{Binding}">
<Button.Content>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
<Rectangle Fill="{DynamicResource Icon_Test}" Margin="4,0,5,0" Height="16" Width="16" />
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding StringFormat="{} {0}({1})">
<Binding Path="Name" />
<Binding Path="ImageCount" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Style>
<Style TargetType="{x:Type ListBox}" BasedOn="{StaticResource ListBoxStyle}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="AutomationProperties.AutomationId" Value="{Binding Name}"/>
</Style>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
</xctk:SplitButton.DropDownContent>
<xctk:SplitButton.Content>
<toolkit:LabelledButton x:Name="TestSeries"
AutomationProperties.AutomationId="TestBtn"
CommandParameter="{Binding ViewerState}" Margin="0,1,0,0" Height="56">
<toolkit:LabelledButton.Content>
<Rectangle Fill="{DynamicResource Icon_Test}" Margin="0,2,0,-5"/>
</toolkit:LabelledButton.Content>
<toolkit:LabelledButton.Style>
<Style TargetType="{x:Type toolkit:LabelledButton}" BasedOn="{StaticResource {x:Type toolkit:LabelledButton}}">
<Setter Property="LabelText" Value="{Binding SelectedImageSeries, Mode=TwoWay}" />
<Setter Property="ToolTip" Value="{Binding SelectedImageSeries, Mode=TwoWay}" />
</Style>
</toolkit:LabelledButton.Style>
</toolkit:LabelledButton>
</xctk:SplitButton.Content>
<xctk:SplitButton.Style>
<Style TargetType="{x:Type xctk:SplitButton}" BasedOn="{StaticResource TestSplitButtonStyle}">
<Setter Property="Visibility" Value="Visible"/>
</Style>
</xctk:SplitButton.Style>
</xctk:SplitButton>
此外,当我单击按钮时,它会执行相关的命令,但下拉菜单不会关闭。
解决方案
您还必须将ListBox.SelectedItem
属性绑定到SelectedImageSeries
.
看起来你使用的SplitButton
太复杂了。我发布了一个简化的解决方案。由于我们现在正确绑定了 中的SelectedImageSeries
项目ListBox
,因此无需在 中Button
添加DataTemplate
a ListBoxItem
。您可以直接在属性设置器中处理所选项目,
而不是执行。为此,TestCommand
我在视图模型中添加了一个方法。OnSelectedImageSeriesChanged
也无需添加另一个按钮 ( LabelButton
) 嵌套到SplitButton.Content
. DataTemplate
您可以通过将 a 分配给属性并将 aSplitButton.ContentTemplate
绑定ICommand
到属性来修改内容布局,SplitButton.Command
并且可以选择使用SplitButton.CommandParameter
.
BindingMode.TwoWay
仅当您将数据发送回数据源时才需要。在您使用它的每个地方都是多余的:LabelText
永远ToolTip
不要发送数据(他们不能)。大多数可以在反映用户输入时发送数据的属性在TwoWay
默认情况下是绑定的,例如TextBox.Text
,ListBox.SelectedItem
等ToggleButton.IsChecked
。
查看模型
class MainViewModel
{
public ObservableCollection<ImageSeries> DropDownContentCollection { get; }
private ImageSeries selectedImageSeries;
public ImageSeries SelectedImageSeries
{
get => this.selectedImageSeries;
set
{
this.selectedImageSeries = value;
OnPropertyChanged();
// Handle ListBox item selected. Replaces command.
OnSelectedImageSeriesChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
拆分按钮
<xctk:SplitButton Width="100"
Content="{Binding SelectedImageSeries}"
Command="{Binding HandleButtonPressedCommand}"
CommandParameter="{Binding ViewerState}">
<xctk:SplitButton.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
<Rectangle Fill="{DynamicResource Icon_Test}" Width="20" Height="20" />
</StackPanel>
</DataTemplate>
</xctk:SplitButton.ContentTemplate>
<xctk:SplitButton.DropDownContent>
<ListBox ItemsSource="{Binding DropDownContentCollection}" SelectedItem="{Binding SelectedImageSeries}" />
</xctk:SplitButton.DropDownContent>
</xctk:SplitButton>
推荐阅读
- ios - iOS/Swift:如何从键盘上删除空格键、返回键和数字键
- python - 在使用 Python 进行迭代期间更改列表中对象的属性
- flutter - 在 Flutter 中定义命名参数
- r - 如何将数据框中的 Tukey HSD p 值括号添加到列表列表中的 ggplots?
- javascript - Javascript Audio Play() 函数不播放所有声音
- javascript - TypeScript 类工厂需要一个交集
- r - R 中的人口模型错误:`$<-.data.frame`(`*tmp*`, "Age", value = NA) 中的错误:替换有 1 行,数据有 0
- typescript - 打字稿错误:TS2345:类型参数'{主题:字符串;json文件:字符串;输出:字符串;}; }' 不可分配给“选项”类型的参数
- javascript - 打字稿/javascript删除嵌套对象数组中的对象部分重复
- templates - UWP:除了 ItemsWrapGrid 之外,还有其他 ItemsPanelTemplate(s)