ComboBox 选定的项目数据触发折叠子用户控件上的按钮
ComboBox selected item data triggers to collapse button on child user control
我想弄清楚如何让数据触发器在用户控件之间工作 - 在 window 和子用户控件(嵌入在 window 中的用户控件)之间,或者在具有子用户控件的用户控件之间。
按钮控件有 5 个按钮,但默认情况下第 5 个按钮是折叠的。选择组合框项目 "Fifth Button" 时,我希望第四个按钮折叠,第五个按钮可见。如您所见,我将触发器设置为根据组合框选择更新 Mainwindow 上的标签。我在同一个 window 中使用触发器没有问题,但我不知道如何让它们与嵌入在同一个 window 中的用户控件进行通信。或者从一个控件到另一个控件。
<Window x:Class="ComboboxControlChange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboboxControlChange"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" x:Name="ButtonSelectCombobox" SelectedValuePath="Content" SelectedValue="{Binding ButtonSelection}" Height="24" Margin="150,0">
<ComboBoxItem x:Name="FirstButtonSelection" >First Button</ComboBoxItem>
<ComboBoxItem x:Name="SecondButtonSelection">Second Button</ComboBoxItem>
<ComboBoxItem x:Name="ThirdButtonSelection">Third Button</ComboBoxItem>
<ComboBoxItem x:Name="FourthButtonSelection">Fourth Button</ComboBoxItem>
<ComboBoxItem x:Name="FifthButtonSelection">Fifth Button</ComboBoxItem>
</ComboBox>
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Vertical">
<Label>You have selected button:</Label>
<Label HorizontalAlignment="Center">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Content" Value=""/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FirstButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="One" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SecondButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Two" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=ThirdButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Three" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FourthButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Four" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Five" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Row="1">
<local:ButtonControl />
</Grid>
</Grid>
</Window>
<UserControl x:Class="ComboboxControlChange.ButtonControl"
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:local="clr-namespace:ComboboxControlChange"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="517">
<Grid Name="Link1MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" VerticalAlignment="Center" Margin="5,0" >
<TextBlock TextAlignment="Center">
First<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="1" VerticalAlignment="Center" Margin="5,0">
<TextBlock TextAlignment="Center">
Second<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="2" VerticalAlignment="Center" Margin="5,0">
<TextBlock TextAlignment="Center">
Third<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="3" VerticalAlignment="Center" Margin="5,0" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<TextBlock TextAlignment="Center">
Fourth<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="3" Margin="4,4,4,50" Visibility="Collapsed">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<TextBlock TextAlignment="Center">
Fifth<LineBreak/>Button
</TextBlock>
</Button>
</Grid>
</UserControl>
我试过用 ElementName、Path 甚至 relativeSource 绑定按钮,但都没有成功。我还尝试在控件的 ButtonControl.Resources 部分添加触发器。
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<DataTrigger Binding="{Binding RelativeSource={RelatvieSource FindAncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="true">
如有任何帮助,我们将不胜感激!
这将不起作用,因为 window 中的元素名称将不在用户控件的范围内。 MSDN 说:
[...] the primary XAML namescope is defined at the XAML root element of a
single XAML production, and encompasses the elements that are
contained in that XAML production.
实际上,这意味着当您为文件中的元素定义 x:Name 时,它只能在该文件中引用,并且在文件外部是未知的。
解决此问题的另一种方法是在用户控件上创建一个 Dependency Property,并将其用作在 window 和控件之间传递信息的方式。一个很好的副作用是这会创建一些抽象并允许更大的灵活性。
ButtonControl.xaml.cs:(将 'Feature' 重命名为相关名称)
public partial class ButtonControl : UserControl
{
...
public bool IsFeatureVisible
{
get { return (bool)GetValue(IsFeatureVisibleProperty); }
set { SetValue(IsFeatureVisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for IsFeatureVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsFeatureVisibleProperty =
DependencyProperty.Register("IsFeatureVisible", typeof(bool), typeof(ButtonControl), new UIPropertyMetadata(false));
...
}
现在你可以连接触发器来使用这个属性,但我们很幸运,在这种情况下你正在处理布尔值和可见性,所以我们可以让它更简单:
ButtonControl.xaml:
<UserControl x:Class="ComboboxControlChange.ButtonControl"
x:Name="Myself"
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:local="clr-namespace:ComboboxControlChange"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="517">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="mBooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid Name="Link1MainGrid">
...
<Button Grid.Column="3" VerticalAlignment="Center" Margin="5,0" Visibility="{Binding ElementName=Myself, Path=IsFeatureVisible, Converter={StaticResource mBooleanToVisibilityConverter}}">
<TextBlock TextAlignment="Center">
Fourth<LineBreak/>Button
</TextBlock>
</Button>
...
</Grid>
</UserControl>
最后,在 Window 中,我们需要在按钮控件的实例中为 属性 提供一个值。我们可以在这里使用 FifthButtonSelection 元素名称,就像您在文件的其他部分中一样:
MainWindow.xaml
<local:ButtonControl IsFeatureVisible="{Binding ElementName=FifthButtonSelection, Path=IsSelected}"/>
我想弄清楚如何让数据触发器在用户控件之间工作 - 在 window 和子用户控件(嵌入在 window 中的用户控件)之间,或者在具有子用户控件的用户控件之间。
按钮控件有 5 个按钮,但默认情况下第 5 个按钮是折叠的。选择组合框项目 "Fifth Button" 时,我希望第四个按钮折叠,第五个按钮可见。如您所见,我将触发器设置为根据组合框选择更新 Mainwindow 上的标签。我在同一个 window 中使用触发器没有问题,但我不知道如何让它们与嵌入在同一个 window 中的用户控件进行通信。或者从一个控件到另一个控件。
<Window x:Class="ComboboxControlChange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboboxControlChange"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" x:Name="ButtonSelectCombobox" SelectedValuePath="Content" SelectedValue="{Binding ButtonSelection}" Height="24" Margin="150,0">
<ComboBoxItem x:Name="FirstButtonSelection" >First Button</ComboBoxItem>
<ComboBoxItem x:Name="SecondButtonSelection">Second Button</ComboBoxItem>
<ComboBoxItem x:Name="ThirdButtonSelection">Third Button</ComboBoxItem>
<ComboBoxItem x:Name="FourthButtonSelection">Fourth Button</ComboBoxItem>
<ComboBoxItem x:Name="FifthButtonSelection">Fifth Button</ComboBoxItem>
</ComboBox>
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Vertical">
<Label>You have selected button:</Label>
<Label HorizontalAlignment="Center">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Content" Value=""/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FirstButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="One" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SecondButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Two" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=ThirdButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Three" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FourthButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Four" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelection, Path=IsSelected}" Value="true">
<Setter Property="Content" Value="Five" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Row="1">
<local:ButtonControl />
</Grid>
</Grid>
</Window>
<UserControl x:Class="ComboboxControlChange.ButtonControl"
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:local="clr-namespace:ComboboxControlChange"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="517">
<Grid Name="Link1MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" VerticalAlignment="Center" Margin="5,0" >
<TextBlock TextAlignment="Center">
First<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="1" VerticalAlignment="Center" Margin="5,0">
<TextBlock TextAlignment="Center">
Second<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="2" VerticalAlignment="Center" Margin="5,0">
<TextBlock TextAlignment="Center">
Third<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="3" VerticalAlignment="Center" Margin="5,0" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<TextBlock TextAlignment="Center">
Fourth<LineBreak/>Button
</TextBlock>
</Button>
<Button Grid.Column="3" Margin="4,4,4,50" Visibility="Collapsed">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<TextBlock TextAlignment="Center">
Fifth<LineBreak/>Button
</TextBlock>
</Button>
</Grid>
</UserControl>
我试过用 ElementName、Path 甚至 relativeSource 绑定按钮,但都没有成功。我还尝试在控件的 ButtonControl.Resources 部分添加触发器。
<DataTrigger Binding="{Binding ElementName=FifthButtonSelected, Path=IsSelected}" Value="true">
<DataTrigger Binding="{Binding RelativeSource={RelatvieSource FindAncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="true">
如有任何帮助,我们将不胜感激!
这将不起作用,因为 window 中的元素名称将不在用户控件的范围内。 MSDN 说:
[...] the primary XAML namescope is defined at the XAML root element of a single XAML production, and encompasses the elements that are contained in that XAML production.
实际上,这意味着当您为文件中的元素定义 x:Name 时,它只能在该文件中引用,并且在文件外部是未知的。
解决此问题的另一种方法是在用户控件上创建一个 Dependency Property,并将其用作在 window 和控件之间传递信息的方式。一个很好的副作用是这会创建一些抽象并允许更大的灵活性。
ButtonControl.xaml.cs:(将 'Feature' 重命名为相关名称)
public partial class ButtonControl : UserControl
{
...
public bool IsFeatureVisible
{
get { return (bool)GetValue(IsFeatureVisibleProperty); }
set { SetValue(IsFeatureVisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for IsFeatureVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsFeatureVisibleProperty =
DependencyProperty.Register("IsFeatureVisible", typeof(bool), typeof(ButtonControl), new UIPropertyMetadata(false));
...
}
现在你可以连接触发器来使用这个属性,但我们很幸运,在这种情况下你正在处理布尔值和可见性,所以我们可以让它更简单:
ButtonControl.xaml:
<UserControl x:Class="ComboboxControlChange.ButtonControl"
x:Name="Myself"
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:local="clr-namespace:ComboboxControlChange"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="517">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="mBooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid Name="Link1MainGrid">
...
<Button Grid.Column="3" VerticalAlignment="Center" Margin="5,0" Visibility="{Binding ElementName=Myself, Path=IsFeatureVisible, Converter={StaticResource mBooleanToVisibilityConverter}}">
<TextBlock TextAlignment="Center">
Fourth<LineBreak/>Button
</TextBlock>
</Button>
...
</Grid>
</UserControl>
最后,在 Window 中,我们需要在按钮控件的实例中为 属性 提供一个值。我们可以在这里使用 FifthButtonSelection 元素名称,就像您在文件的其他部分中一样:
MainWindow.xaml
<local:ButtonControl IsFeatureVisible="{Binding ElementName=FifthButtonSelection, Path=IsSelected}"/>