【问题标题】:Button Visibility According To Listbox ListboxItem Selection根据 Listbox ListboxItem 选择的按钮可见性
【发布时间】:2014-12-22 08:33:43
【问题描述】:

我的情况如下

我想在未选择任何项目时隐藏删除按钮并在选择某项时显示。

如果用户选择一个项目并在其他地方单击(这表示该用户不再使用列表框),也会隐藏该按钮。

我尝试了LostFocus 事件,检查SelectedIndex 等,但没有成功。知道怎么做吗?

    private void ListBoxItem_LostFocus(object sender, RoutedEventArgs e)
    {
        if (button.IsFocused != true) // checking if user has selected an item & clicking on button (valid action)
        {
            listbox.SelectedIndex = -1;
        }
    }

    private void listbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (listbox.SelectedIndex == -1)
        {
            button.Visibility = Visibility.Hidden;
        }
        else
        {
            button.Visibility = Visibility.Visible;
        }
    }

【问题讨论】:

  • 向我们展示你目前的工作:)
  • 从可用性的角度来看,这是一个非常非常糟糕的主意。想象一下第一次或很少查看您的应用程序的人。他/她必须知道/记住,在没有选择项目并且列表框被聚焦之前,可用操作的完整列表是不清楚的。这不是很明显,最好总是显示按钮,但在无法进行相关操作时禁用它。
  • @Dennis:是的,我同意。但就我而言,根据 UI 的设计,简单性很重要。用户不应该看到所有启用/禁用的东西,但它应该在必要时可用。

标签: c# wpf listbox show-hide


【解决方案1】:

约瑟夫的回答是正确的,但你不需要转换器。

你可以用一个简单的触发器来达到同样的效果:

<ListBox>
    ...
    <ListBox.Style>
        <Style TargetType="{x:Type ListBox}">
            <Style.Triggers>
                <Trigger Property="SelectedItem" Value="{x:Null}">
                    <Setter TargetName="YOUR_BUTTON'S_NAME" Property="Visibility" Value="Hidden"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.Style>
</ListBox>

编辑:在样式设置器中使用 TargetName 确实是不可能的。

所以,我能做的最接近的解决方案是创建一个 DataTrigger:

<DockPanel LastChildFill="True">
    <Button DockPanel.Dock="Top">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=MyList, Path=SelectedItem}"
                                 Value="{x:Null}">
                        <Setter Property="Visibility" Value="Hidden"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        <TextBlock Text="Button"/>
    </Button>
    <ListBox x:Name="MyList">
        <TextBlock Text="Something"/>
        <TextBlock Text="Something"/>
        <TextBlock Text="Something"/>
        <TextBlock Text="Something"/>
        <TextBlock Text="Something"/>
    </ListBox>
</DockPanel>

【讨论】:

  • 错误 - The name "button1" is not recognized.
  • @MangeshGhotage 如果按钮的 x:Name 是 button1,它应该可以工作
  • 很奇怪。请加入此聊天并粘贴您的 xaml:chat.stackoverflow.com/rooms/67482/wpf-quest-mangeshghotage
  • 有没有解决“无法识别”的问题?我正在尝试基本上做这件事(好吧,启用/禁用基于SelectedIndex属性的按钮),虽然我认为我可以从列表框样式中引用按钮或从按钮中引用列表框风格,我也想不通。不幸的是,您创建的聊天已被删除,并且此答案尚未更新以反映任何解决方案。 :(
  • @PeterDuniho 我的回答确实不正确,因为您不能在样式中使用 Setter 的 TargetName。一种解决方法是使用绑定集的 ElementName 或 RelativeSource 的 DataTrigger(我使用有效的解决方案编辑了我的答案)。
【解决方案2】:

对于问题的前半部分,最好的方法是使用如下转换器: 1.添加一个Converter类:

 public class VisibilityConverter:IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (value == null ? Visibility.Hidden : Visibility.Visible);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

2.添加到Window资源中:

<Window.Resources>
        <wpfApplication:VisibilityConverter x:Key="VisibilityConverter"/>
</Window.Resources>

3。并用它来隐藏/显示您的按钮:

<Grid>
       <Grid.RowDefinitions>
           <RowDefinition Height="Auto"/>
           <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
        <ListBox HorizontalAlignment="Center" x:Name="listBox">
            <ListBoxItem Content="Fist"/>
            <ListBoxItem Content="Second"/>
            <ListBoxItem Content="Third"/>
            <ListBoxItem Content="Fourth"/>
        </ListBox>
        <Button Content="delete" Grid.Row="1" HorizontalAlignment="Center" Visibility="{Binding SelectedItem,ElementName=listBox,Converter={StaticResource VisibilityConverter}}"/>
    </Grid>

对于问题的后半部分,您必须处理窗口中的MouseDown 事件:

MouseDown="MainWindow_OnMouseDown"

并添加以下处理程序(这会将列表的SelectedItem 重置为null

 private void MainWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            listBox.SelectedItem = null;
        }

【讨论】:

  • 1) 转换器在这里是多余的,一个简单的数据触发器就足够了。 2)以这种方式处理鼠标事件也会隐藏一个按钮,当用户尝试点击它时(虽然,我不确定,现在不能检查)。实际上,就目前而言,这个问题并不是一条可行的路。
  • 对。因此,请随意发布所属的 MVVM 解决方案。
  • 否,当按钮或列表收到单击时,它不会被窗口拦截,是的,我有点同意你的观点,即使用转换器有点过度工作,但我相信它是一种方法。
  • @deafjeff 什么 Mvvm 解决方案!!
  • @Joseph 使用 IPropertyChanged,不更改代码中的按钮可见性。
【解决方案3】:

单独运行此代码并尝试。它在这里为我工作。

  <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <StackPanel>
        <ListBox x:Name="lst">
            <ListBox.Triggers>
                <EventTrigger RoutedEvent="GotFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Visible}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard> 
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="LostFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Collapsed}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </ListBox.Triggers>
            <ListBoxItem>ListBoxItem1</ListBoxItem>
            <ListBoxItem>ListBoxItem2</ListBoxItem>
            <ListBoxItem>ListBoxItem3</ListBoxItem>
            <ListBoxItem>ListBoxItem4</ListBoxItem>
        </ListBox>
        <Button x:Name="DeleteButton"  Content="Delete" Height="30" Width="100">
            <Button.Style>
                <Style BasedOn="{StaticResource alredayDefinedStyleKey}"  TargetType="Button">
                    <Setter Property="Visibility" Value="Visible"></Setter>
                    <Style.Triggers>                           
                        <DataTrigger Binding="{Binding Path=SelectedItem, ElementName=lst}" Value="{x:Null}" >
                            <Setter Property="Visibility" Value="Collapsed"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>

    <ListBox Grid.Column="1">
        <ListBoxItem>1</ListBoxItem>
        <ListBoxItem>2</ListBoxItem>
    </ListBox>
</Grid>

【讨论】:

  • 这似乎很简单且工作..只是一点帮助..当我点击按钮时,它会触发点击事件并消失。我可以防止它在点击时隐藏吗?否则它就像一个魅力!
  • 将属性 Focusable="False" 设置为按钮
  • 我想将此应用于多个按钮。我的意思是,我有 3 个选项按钮,我需要为所有这些按钮做同样的事情。他们也已经应用了一些其他样式。请您为这种情况提供解决方案吗?
  • prntscr.com/5jq13c。请具体说明您的要求..........您想在列表框单项选择上显示所有 3 个按钮吗?
【解决方案4】:

LostFocus 只会在元素失去逻辑焦点时触发。使用LostKeyboardFocus 事件。那你就近了一步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 2023-03-18
    • 2014-03-01
    • 2019-01-16
    • 2013-06-30
    • 1970-01-01
    相关资源
    最近更新 更多