开发者

Changing elements of a toolbar from collapsed to visible doesn't change their visibility

I've just spend my whole evening trying to understand and fix an issue that I'm currently encountering with a toolbar :

I've created a tiny vector based drawing program in which the user can choose a tool (selection, line, text, image, etc...), by clicking on the corresponding icon located in a toolbar before using it.

When a certain tool is selected, new controls appear in the toolbar (they have their visibility, which is originally set to collapsed, changed to visible), allowing the user to change its parameters.

For instance when clicking on the text tool, a field appear where the user can write the content. When the image tool is selected, a button appears that opens an OpenFileDialog (in order to select the source file), etc etc...

The problem is that, in a very particular situation, some elements that should appear when their corresponding tool is selected, stay hidden, even with their visibility set to true in code. And the missing controls are not in the overflow part of the toolbar either.

It's pretty hard to explain so here is a source code example, which mimics my app and shows the issue : create a new C# wpf project, then copy the following code in the 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>
    <Scro开发者_如何学PythonllViewer HorizontalScrollBarVisibility="Visible">
        <Canvas Name="workspace" Background="White">

        </Canvas>
    </ScrollViewer>
</DockPanel>

And the following lines in the corresponding *.cs file :

using System.Windows;

namespace DDI
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            SelectSelectionTool();
        }

        private void tool_selection_Click(object sender, RoutedEventArgs e)
        {
            SelectSelectionTool();
        }

        private void tool_text_Click(object sender, RoutedEventArgs e)
        {
            SelectTextTool();
        }

        private void tool_image_Click(object sender, RoutedEventArgs e)
        {
            SelectImageTool();
        }

        private void SelectSelectionTool()
        {
            tool_selection.IsChecked = true;
            tool_text.IsChecked = false;
            tool_image.IsChecked = false;

            tool_separator1.Visibility = Visibility.Collapsed;

            tool_name_caption.Visibility = Visibility.Collapsed;
            tool_name_field.Visibility = Visibility.Collapsed;

            tool_content_caption.Visibility = Visibility.Collapsed;
            tool_content_field.Visibility = Visibility.Collapsed;

            tool_source_caption.Visibility = Visibility.Collapsed;
            tool_source_field.Visibility = Visibility.Collapsed;
            tool_source_select.Visibility = Visibility.Collapsed;

            tool_z_caption.Visibility = Visibility.Collapsed;
            tool_z_field.Visibility = Visibility.Collapsed;
        }

        private void SelectTextTool()
        {
            tool_selection.IsChecked = false;
            tool_text.IsChecked = true;
            tool_image.IsChecked = false;

            tool_separator1.Visibility = Visibility.Visible;

            tool_name_caption.Visibility = Visibility.Visible;
            tool_name_field.Visibility = Visibility.Visible;

            tool_content_caption.Visibility = Visibility.Visible;
            tool_content_field.Visibility = Visibility.Visible;

            tool_source_caption.Visibility = Visibility.Collapsed;
            tool_source_field.Visibility = Visibility.Collapsed;
            tool_source_select.Visibility = Visibility.Collapsed;

            tool_z_caption.Visibility = Visibility.Visible;
            tool_z_field.Visibility = Visibility.Visible;
        }

        private void SelectImageTool()
        {
            tool_selection.IsChecked = false;
            tool_text.IsChecked = false;
            tool_image.IsChecked = true;

            tool_separator1.Visibility = Visibility.Visible;

            tool_name_caption.Visibility = Visibility.Visible;
            tool_name_field.Visibility = Visibility.Visible;

            tool_content_caption.Visibility = Visibility.Collapsed;
            tool_content_field.Visibility = Visibility.Collapsed;

            tool_source_caption.Visibility = Visibility.Visible;
            tool_source_field.Visibility = Visibility.Visible;
            tool_source_select.Visibility = Visibility.Visible;

            tool_z_caption.Visibility = Visibility.Visible;
            tool_z_field.Visibility = Visibility.Visible;
        }
    }
}

Now launch the application. Do not try to resize it now, in order to see the issue !

The yellow tool is the one currently selected. Now proceed in this order : Click on the red button : new elements appear. Click on the blue button : some elements stay, some disappear. But oddly some are missing : the "Source :" TexBlock, the tool_source_file textbox and the "..." button. Try to resize the window : the three missing controls appear by magic (they were not present in the overflow part of the toolbar, which wasn't active before)

Another way to see the issue :

  • Launch the app.
  • The yellow tool is the one currently selected.
  • Click on the red button.
  • Click on the blue button.
  • Click on the red button.
  • Click on the blue button : the three missing controls now appear in the right place !

My question is simple : what's going on ?

I've tried a lot of things including using the different version of invalidate with the toolbar after changing items visibility, splitting the toolbar in two panels, etc. , but nothing worked.


Thanks for your answers.

I will try your code shortly Tony.

I've also submited the issue on microsoft website, but apparently they don't look at suggestions unless they get 5 votes. So please, vote for it : https://connect.microsoft.com/WPF/feedback/details/638552/changing-visibility-of-toolbar-components-to-visible-does-not-make-them-appear-event-in-the-overflow-part-of-the-toolbar#details

Regards


I don´t know, but this seems to be a bug. For now, you can try to do this to solve your problem:

    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();
    }

Note: The Refresh() method is Extension method that I use on my projects:

// 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);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜