WPF 绑定不更新可见性

Posted

技术标签:

【中文标题】WPF 绑定不更新可见性【英文标题】:WPF Binding not updating Visibility 【发布时间】:2016-01-31 13:23:57 【问题描述】:

我在绑定到网格的可见性时遇到了问题。我以前做过一些项目,并尝试复制以前使用的相同编码,我已经四处搜索并根据其他一些文章添加了 bool 到可见性转换器,但仍然没有。

到目前为止,我在这个项目中所做的只是提供一组将提供给用户的选项。当他们选择一个选项时,它会显示子选项或将它们带到适当的区域。我将绑定设置为 bool 对象,并且有时会创建小消息框和其他消息框,只是为了让我知道程序是否无处不在。一路走来,我得到了每一个消息框,所以它似乎到达了每一段代码。

任何人都可以阐明我做错了什么或指出我正确的方向吗?

Windows.Resources 中的转换器(已编辑以显示 Windows.Resources 中的所有代码)

<Window.Resources>
    <Style TargetType="x:Type Button">
        <Setter Property="FontSize" Value="15"/>
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Height" Value="50" />
        <Setter Property="Width" Value="100" />
        <Setter Property="Margin" Value="0,0,0,0" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>

窗口其余部分的代码

<Grid>
    <Grid x:Name="grid_mainMenu" Visibility="Binding MainMenuVisibility, Converter=StaticResource BooleanToVisibilityConverter" Margin="0,0,0,20">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Button x:Name="button_Items" Content="Items" Grid.Row="0" Click="button_Items_Click"/>
        <Button x:Name="button_Orders" Content="Orders" Grid.Row="1" Click="button_Orders_Click" />
        <TextBox Text="Binding StatusMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Margin="0,0,0,0" HorizontalAlignment="Left"  VerticalAlignment="Top" Height="100" Width="100"/>
    </Grid>
    <Grid x:Name="grid_itemMenu" Visibility="Binding ItemMenuVisibility, Converter=StaticResource BooleanToVisibilityConverter" Margin="0,0,0,20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Label Content="Item Menu" Grid.Row="0" FontSize="20" FontWeight="Bold" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Button Grid.Row="1" x:Name="button_itemMaintenance" Content="Maintenance"/>
        <Button Grid.Row="2" x:Name="button_itemCreation" Content="Create"/>
    </Grid>
    <DockPanel Height="25" Margin="0,0,0,0" VerticalAlignment="Bottom">
        <StatusBar DockPanel.Dock="Bottom">
            <StatusBarItem>
                <TextBlock Text="Binding StatusMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
            </StatusBarItem>
        </StatusBar>
    </DockPanel>
</Grid>

这是类中的代码

    public bool MainMenuVisibility
    
        get  return _mainMenuVisibility; 
        set  _mainMenuVisibility = value; RaisePropertyChanged(); 
    

    public bool ItemMenuVisibility
    
        get  return _itemMenuVisibility; 
        set
         _itemMenuVisibility = value; RaisePropertyChanged(); 
    

    public bool OrderMenuVisibility
    
        get  return _orderMenuVisibility; 
        set  _orderMenuVisibility = value;  RaisePropertyChanged(); 
    

主构造函数

public Menu_View()
    
        ShowMainMenu();
    

几个控件

public void ShowMainMenu()
    
        MainMenuVisibility = true;
        HideItemMenu();
        HideOrderMenu();
        StatusMessage = "Showing main menu";
    

    public void HideMainMenu()
    
        MainMenuVisibility = false;
        StatusMessage = "Hid main menu";
    

    public void ShowItemMenu()
    
        try
        
            //Reaches, but never updates
            ItemMenuVisibility = true;
            HideMainMenu();
            HideOrderMenu();
        
        catch(Exception error)
        
            //Never shows anything here
            StatusMessage = "Failed to load item menu";
        
        finally
        
            //Does not update, but reaches here
            StatusMessage = "Showing item menu";
        
    

程序首先显示主菜单,当用户单击项目按钮时,它应该显示项目菜单。按钮单击调用 ShowItemMenu()。我已验证确实会发生这种情况并按正确的顺序调用。

我已经验证了 ShowItemMenu() 确实有效,但放入了构造函数而不是 ShowMainMenu()。任何一个都可以正常工作,但即使在按下按钮后到达,也不会在初始加载后导致更新。

对不起,如果我没有包括我需要的一切。

编辑:

我相信我实际上同时遇到了两个问题。一种是配置不当的数据转换器。答案和参考如下。

以及我的窗口代码中的一个问题:

public MainWindow()
    
        InitializeComponent();
        menuView = new Menu_View();
        this.DataContext = new Menu_View();
    

    Menu_View menuView;

我相信这是问题的一部分。我正在创建一个 Menu_View 类型的 menuView。在初始化时,我将 menuView 分配给了一个新的 Menu_View(),然后将我的 DataContext 分配给了一个新的 Menu_View() 而不是 menuView。所有命令都在更新 menuView,而我正在更新分配给 DataContext 的命令。

【问题讨论】:

您能否将您的根面板从 Grid 修改为 StackPanel,并告诉我们效果如何? 你能显示你的 BooleanToVisibilityConverter 代码吗 我怀疑问题出在您的转换器代码上。保留断点并检查它是否返回正确的输出。 @AbinMathew 我已编辑以显示 Windows.Resources 中的所有内容。转换器是我在阅读了一篇文章后尝试的,我正在使用的转换器默认包含在 Visual Studio 中。我最初使用 Visibility.Hidden 和 Visibility.Visible 没有更新。 @tagaPdyk 我已将 Grid 更改为 StackPanel,但仍然没有更新。 【参考方案1】:

将此converter 类添加到您的项目中。

 class BooleanToVisibilityConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    
        if (value is Boolean && (bool)value)
        
            return Visibility.Visible;
        
        return Visibility.Collapsed;
    

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    
        if (value is Visibility && (Visibility)value == Visibility.Visible)
        
            return true;
        
        return false;
    

Referance

【讨论】:

我已将代码添加为一个类。没有变化。我在应该导致任何更改的每一步都设置断点。每个值都完全按照我的预期变化,但没有任何变化反映在 GUI 中。唯一这样做的是我添加的文本框,只是为了检查数据绑定和 notifypropertychanged。文本框完美更新状态框。 它似乎没有在任何地方调用新类。 这是你将你的类与 xaml 链接的地方 请点击我添加到答案中的参考资料会让你更清楚。 感谢您在设置数据转换器方面的帮助。我以前从未设置过,并且在一篇文章的推荐下使用它。每次需要开火时,我都会让它开火。【参考方案2】:

如果您愿意,您可以不使用布尔转换器。您不必编写任何代码隐藏。

<Grid>
    <Grid.Style>
        <Style TargetType="x:Type Grid">
            <Setter Property="Visibility" Value="Collapsed" />
            <Style.Triggers>
                <DataTrigger Binding="Binding Path=MyBoolValue" Value="True">
                    <Setter Property="Visibility" Value="Visible" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

【讨论】:

以上是关于WPF 绑定不更新可见性的主要内容,如果未能解决你的问题,请参考以下文章

WPF:可见性绑定,事件 = null

WPF DataGrid的可见性

我可以将 WPF ComboBox 控件的可见性绑定到从命令获得的项目的存在/不存在吗? [关闭]

如何使用 WPF 中的代码绑定 DataGridTextColumn 的可见性属性?

WPF - 将 UserControl 可见性绑定到属性

WPF:通过字符串内容绑定可见性