C# 将工具栏的元素从折叠更改为可见不会';不要改变他们的能见度

C# 将工具栏的元素从折叠更改为可见不会';不要改变他们的能见度,c#,wpf,visibility,C#,Wpf,Visibility,我整个晚上都在试图理解和解决我目前在工具栏上遇到的一个问题: 我已经创建了一个基于向量的绘图程序,用户可以在使用之前单击工具栏中相应的图标来选择工具(选择、线条、文本、图像等) 选择某个工具后,工具栏中会出现新控件(它们的可见性最初设置为“折叠”,更改为“可见”),允许用户更改其参数 例如,单击文本工具时,会出现一个字段,用户可以在其中写入内容。选择图像工具时,会出现一个按钮,打开OpenFileDialog(以选择源文件),等等 问题是,在一个非常特殊的情况下,当选择相应的工具时应该出现的一些

我整个晚上都在试图理解和解决我目前在工具栏上遇到的一个问题:

我已经创建了一个基于向量的绘图程序,用户可以在使用之前单击工具栏中相应的图标来选择工具(选择、线条、文本、图像等)

选择某个工具后,工具栏中会出现新控件(它们的可见性最初设置为“折叠”,更改为“可见”),允许用户更改其参数

例如,单击文本工具时,会出现一个字段,用户可以在其中写入内容。选择图像工具时,会出现一个按钮,打开OpenFileDialog(以选择源文件),等等

问题是,在一个非常特殊的情况下,当选择相应的工具时应该出现的一些元素保持隐藏,即使在代码中它们的可见性设置为true。缺少的控件也不在工具栏的溢出部分

这很难解释,因此这里有一个源代码示例,它模仿了我的应用程序并显示了问题:创建一个新的C#wpf项目,然后在MainWindow.xaml中复制以下代码

<Window x:Class="DDI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DDI" Height="250" Width="318">
<DockPanel Width="Auto" Height="Auto" LastChildFill="True">
    <StackPanel DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
        <Menu>
            <MenuItem Header="Fichier">
                <MenuItem Header="Nouveau" />
                <MenuItem Header="Ouvrir" />
                <Separator />
                <MenuItem Header="Quitter" />
            </MenuItem>
        </Menu>
        <ToolBar Name="toolbar">
            <ToggleButton Name="tool_selection" Height="16" Width="16" Click="tool_selection_Click" Background="Yellow">
            </ToggleButton>
            <ToggleButton Name="tool_text" Height="16" Width="16" Click="tool_text_Click" Background="Red">
            </ToggleButton>
            <ToggleButton Name="tool_image" Height="16" Width="16" Click="tool_image_Click" Background="Blue">
            </ToggleButton>
            <Separator Name="tool_separator1" Margin="4,2" />
            <TextBlock Name="tool_name_caption" VerticalAlignment="Center" Margin="0,0,4,0" Visibility="Collapsed">
                Name :
            </TextBlock>
            <TextBox Name="tool_name_field" Width="80" BorderBrush="#FF6F6F6F" Visibility="Collapsed">
            </TextBox>
            <TextBlock Name="tool_content_caption" VerticalAlignment="Center" Margin="4,0,4,0" Visibility="Collapsed">
                Content :
            </TextBlock>
            <TextBox Name="tool_content_field" Width="100" BorderBrush="#FF6F6F6F" Visibility="Collapsed">
                Your text
            </TextBox>
            <TextBlock Name="tool_source_caption" VerticalAlignment="Center" Margin="4,0,4,0" Visibility="Collapsed">
                Source :
            </TextBlock>
            <TextBox Name="tool_source_field" Width="80" BorderBrush="#FF6F6F6F" IsReadOnly="True" AllowDrop="False" Visibility="Collapsed">
            </TextBox>
            <Button Name="tool_source_select" BorderBrush="#FF6F6F6F" Visibility="Collapsed">
                ...
            </Button>
            <TextBlock Name="tool_z_caption" VerticalAlignment="Center" Margin="4,0,4,0" Visibility="Collapsed">
                Z :
            </TextBlock>
            <TextBox Name="tool_z_field" Width="30" BorderBrush="#FF6F6F6F" Visibility="Collapsed">
                0
            </TextBox>
        </ToolBar>
    </StackPanel>
    <ScrollViewer HorizontalScrollBarVisibility="Visible">
        <Canvas Name="workspace" Background="White">

        </Canvas>
    </ScrollViewer>
</DockPanel>
现在启动应用程序。现在不要尝试调整它的大小,以便查看问题

黄色工具是当前选定的工具。 现在按以下顺序进行: 单击红色按钮:出现新元素。 单击蓝色按钮:一些元素保留,一些元素消失。但奇怪的是,其中有一些丢失了:“Source:”TexBlock、tool_Source_file文本框和“…”按钮。 尝试调整窗口大小:三个缺少的控件以魔术的方式出现(它们不存在于工具栏的溢出部分,该部分以前未处于活动状态)

另一种看待问题的方式:

  • 启动应用程序
  • 黄色工具是当前选定的工具
  • 点击红色按钮
  • 点击蓝色按钮
  • 点击红色按钮
  • 单击蓝色按钮:三个缺少的控件现在显示在正确的位置
我的问题很简单:发生了什么

我尝试了很多方法,包括在更改项目可见性后使用工具栏的不同版本的invalidate、将工具栏拆分为两个面板等,但都没有效果


谢谢你的回答

我很快就会试试你的代码,托尼

我也在微软网站上提交了这个问题,但很明显,除非他们得到5票,否则他们不会考虑建议。因此,请投赞成票:


关于

我不知道,但这似乎是一个bug。 现在,您可以尝试这样做来解决您的问题:

    private void tool_image_Click(object sender, RoutedEventArgs e)
    {
        SelectImageTool();
        ChangeWidthAndRefresh();  // this call will hopefully make the toolbar to show the correct controls... :)
    }


    // temp workaround for a weird bug. 
    void ChangeWidthAndRefresh()
    {
        var old_Width = this.Width;
        this.Width = old_Width - 1;
        this.Refresh();
        this.Width = old_Width;
        this.Refresh();
    }
注意:Refresh()方法是我在项目中使用的扩展方法:

// 05-01-2010
public static class WPFUIRefreshExtensionMethods
{
    // www.tonysistemas.com.br
    private static System.Action EmptyDelegate = delegate() { };

    /// <summary>
    /// Força redesenhar
    /// mesmo que esteja dentro de um loop
    /// </summary>
    /// <param name="uiElement"></param>
    public static void Refresh(this System.Windows.UIElement uiElement)
    {
        //uiElement.UpdateLayout();
        uiElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, EmptyDelegate);
    }
}
//05-01-2010
公共静态类WPFUIRefreshExtensionMethods
{
//www.tonysistemas.com.br
私有静态系统。Action EmptyDelegate=delegate(){};
/// 
///福萨·雷德森哈尔
///这是一条很长的路
/// 
/// 
公共静态无效刷新(此System.Windows.UIElement UIElement)
{
//uiElement.UpdateLayout();
uiElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render,EmptyDelegate);
}
}

我在我的电脑(Win7、.Net 4 SP1 Beta版)上复制了这个似乎是bug的东西。真奇怪。你可以将你的代码和描述提交给他们,也许他们会指出一个方向或检测到一个BUG,并尝试在.NET4最终版SP1p中包含对它的修复。是的,看起来肯定像个BUG
// 05-01-2010
public static class WPFUIRefreshExtensionMethods
{
    // www.tonysistemas.com.br
    private static System.Action EmptyDelegate = delegate() { };

    /// <summary>
    /// Força redesenhar
    /// mesmo que esteja dentro de um loop
    /// </summary>
    /// <param name="uiElement"></param>
    public static void Refresh(this System.Windows.UIElement uiElement)
    {
        //uiElement.UpdateLayout();
        uiElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, EmptyDelegate);
    }
}