Изменение элементов панели инструментов со свернутого на видимый не влияет на их видимость.

Я только что провел весь вечер, пытаясь понять и исправить проблему, с которой я сейчас сталкиваюсь на панели инструментов:

Я создал крошечную векторную программу для рисования, в которой пользователь может выбрать инструмент (выделение, линию, текст, изображение и т. д.), щелкнув соответствующий значок, расположенный на панели инструментов, перед его использованием.

При выборе определенного инструмента на панели инструментов появляются новые элементы управления (у них видимость, изначально установленная как свернутая, изменена на видимую), что позволяет пользователю изменять его параметры.

Например, при нажатии на текстовый инструмент появляется поле, в котором пользователь может написать содержимое. Когда выбран инструмент изображения, появляется кнопка, которая открывает диалоговое окно 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>

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

Теперь запустите приложение. Не пытайтесь изменить его размер сейчас, чтобы увидеть проблему!

Желтый инструмент выбран в данный момент. Теперь действуйте в следующем порядке: Нажмите на красную кнопку: появятся новые элементы. Нажмите на синюю кнопку: некоторые элементы останутся, некоторые исчезнут. Но, как ни странно, некоторые из них отсутствуют: «Источник:» TexBlock, текстовое поле tool_source_file и кнопка «...». Попробуйте изменить размер окна: три недостающих элемента управления появляются по волшебству (их не было в переполненной части панели инструментов, которая раньше не была активной)

Другой способ увидеть проблему:

  • Запустите приложение.
  • Желтый инструмент выбран в данный момент.
  • Нажмите на красную кнопку.
  • Нажмите на синюю кнопку.
  • Нажмите на красную кнопку.
  • Нажмите на синюю кнопку: три недостающих элемента управления теперь появляются в нужном месте!

Мой вопрос прост: что происходит?

Я пробовал много вещей, включая использование другой версии аннулирования с панелью инструментов после изменения видимости элементов, разделения панели инструментов на две панели и т. д., но ничего не сработало.


Спасибо за ваши ответы.

Я скоро попробую твой код, Тони.

Я также представил проблему на веб-сайте Microsoft, но, по-видимому, они не рассматривают предложения, пока не получат 5 голосов. Пожалуйста, проголосуйте за него: https://connect.microsoft.com/WPF/feedback/details/638552/change-visibility-of-toolbar-components-to-visible-does-not-make-ихпоявление-событие-в-переполнении-части-панелиинструментов#детали

С уважением


person thomasc    schedule 25.01.2011    source источник
comment
Я воспроизвел эту вещь, которая кажется ошибкой на моем компьютере (Win7, .Net 4 SP1 Beta). Это действительно странно. Вы можете отправить свой код и описание на connect.microsoft.com, возможно, они укажут направление или обнаружат ОШИБКУ. и ПОПРОБУЙТЕ включить ИСПРАВЛЕНИЕ для него в .Net 4 Final SP1.   -  person Tony    schedule 26.01.2011
comment
ага, точно похоже на баг   -  person Robert Levy    schedule 26.01.2011


Ответы (1)


Я не знаю, но это, кажется, ошибка. На данный момент вы можете попробовать сделать это, чтобы решить вашу проблему:

    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);
    }
}
person Tony    schedule 26.01.2011