Pergunta

Estou criando um 3-coluna de INTERFACE do usuário com grade de divisores entre as colunas.Eu tenho a exigência para salvar o estado das colunas, de modo que se o usuário fecha e reabre o aplicativo olha só como eles deixaram.Mas eu também estou tentando obter as colunas para dividir proporcionalmente - por que eu quero dizer, se você esticar a janela, todos os três painéis de crescer e de se mover da esquerda divisor ele muda a divisão entre a esquerda e o centro de colunas.

O que eu tenho atualmente atinge apenas o primeiro requisito - guarda o estado das larguras de coluna.Eu também fiz as colunas mínimos larguras para todas as três colunas.Mas, como eu a entendo, a maneira de contar uma divisão para dividir proporcionalmente, é a estrela de tamanho larguras de coluna.Desde que eu estou usando a propriedade de Largura já para salvar e restaurar o estado, eu não tenho certeza se eu posso fazer o que eu quiser.

Alguém já conseguiu salvar o estado de larguras de coluna E de ter de dividir a ser proporcional?

Aqui está um código para o que eu tenho atualmente:

   <Grid x:Name="mainGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="leftColumn" Width="{Binding MainWindowLeftColumnWidth, Mode=TwoWay, Source={x:Static prop:Settings.Default}}" MinWidth="200" MaxWidth="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=LeftColumnMaxWidth, Mode=OneWay}"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition x:Name="centerColumn" Width="{Binding MainWindowCenterColumnWidth, Mode=TwoWay, Source={x:Static prop:Settings.Default}}" MinWidth="300" MaxWidth="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=CenterColumnMaxWidth, Mode=OneWay}"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition x:Name="rightColumn" Width="*" MinWidth="500"/>
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="leftPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/>
        <GridSplitter x:Name="leftSplitter" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Width="5" ResizeDirection="Columns"/>
        <StackPanel x:Name="centerPanel" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/>
        <GridSplitter x:Name="rightSplitter" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Width="5" ResizeDirection="Columns"/>
        <StackPanel x:Name="rightPanel" Grid.Column="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" SizeChanged="rightPanel_SizeChanged"/>
    </Grid>

Eu tenho as propriedades de dependência do tipo double para tanto LeftColumnMaxWidth e CenterColumnMaxWidth.E o rightPanel_SizeChanged manipulador, bem como a janela Carregada manipulador de tanto chamar esse método:

    private void CalculateMaxWidths()
    {
          FrameworkElement content = Content as FrameworkElement;
          if (content != null)
          {
              LeftColumnMaxWidth = content.ActualWidth
                                 - leftSplitter.ActualWidth
                                 - centerColumn.ActualWidth
                                 - rightSplitter.ActualWidth
                                 - rightColumn.MinWidth;
              CenterColumnMaxWidth = content.ActualWidth
                                   - leftColumn.ActualWidth
                                   - leftSplitter.ActualWidth
                                   - rightSplitter.ActualWidth
                                   - rightColumn.MinWidth;
          }
    }

Eu ainda tenho algum trabalho a fazer para se certificar de que o redimensionamento da janela não se prenda a coluna da direita.Eu acho que a solução pode estar relacionado a tentar fazer os divisores dividido proporcionalmente.Particularmente o comportamento peculiar do meu set atual é que a esquerda divisor redimensiona as colunas esquerda e direita, e deixa o centro de coluna de tamanho fixo.

Eu não tenho medo de manuseio SizeChanged ou DragDelta para alcançar meus objetivos.Mas o que eu acredito que não pode fazer é, na verdade, defina a propriedade Largura das duas primeiras colunas, que iria destruir a minha ligação para a configuração de usuário que salva o estado.

Obrigado antecipadamente por qualquer ajuda.

Foi útil?

Solução

Então eu acredito que eu já descobriu isso.É possível que alguns valores antigos no meu de configurações.as definições estavam me causando problemas, e é possível que os valores padrão eu coloco me causou problemas.Mas aqui está o que eu fiz:

  1. Mudou a minha definições de utilizador para guardar todos os TRÊS (e não apenas a esquerda duas) larguras de coluna.E salvá-los como seqüências de caracteres.
  2. Definir o padrão as configurações do usuário (assim como a propriedade de largura nas colunas) para algo como 200*.
  3. Defina apenas o MinWidth - não o max. - em todos os três colunas.
  4. Carregar manualmente e guardar as definições do utilizador para as colunas utilizando um GridLengthConverter.

Eu não estou 100% convencido de que este é o melhor caminho, mas ele não parece funcionar, o que me faz muito feliz.No caso de mais alguém tem problemas e vem através deste post, aqui está a trabalhar XAML:

    <Grid x:Name="mainGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="leftColumn" MinWidth="200" Width="200*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition x:Name="centerColumn" MinWidth="300" Width="300*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition x:Name="rightColumn" MinWidth="498" Width="498*"/>
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="leftPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/>
        <GridSplitter x:Name="leftSplitter" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Width="5" ResizeDirection="Columns"/>
        <StackPanel x:Name="centerPanel" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/>
        <GridSplitter x:Name="rightSplitter" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Width="5" ResizeDirection="Columns"/>
        <StackPanel x:Name="rightPanel" Grid.Column="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" SizeChanged="rightPanel_SizeChanged"/>
    </Grid>

Que tamanho alterado evento ainda está lá apenas para o rastreamento de depuração.Eu de saída os valores de Largura para ver o que está acontecendo.Curiosamente, após uma expansão de tudo e voltar para a janela do tamanho mínimo, o direito de largura de coluna estadias maiores.Mas desde que todos eles têm minwidths e as larguras de todas as estrelas de tamanho, trabalha-se para fora.

Eu tentei colocar isso de volta em uma ligação, mas desde que eu sou agora armazenar uma cadeia de caracteres, e o GridLengthConverter é um TypeConverter, não o ivalueconverter, não funcionou.Eu acho que pode ser possível para armazenar os valores como GridLengths, embora eu tenha chegado a um ponto em que eu estou feliz com o que eu tenho feito.Então, a minha carregar e salvar são como este:

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        //...

        try
        {
            GridLengthConverter converter = new GridLengthConverter();
            leftColumn.Width = (GridLength)converter.ConvertFromString(Settings.Default.MainWindowLeftColumnWidth);
            centerColumn.Width = (GridLength)converter.ConvertFromString(Settings.Default.MainWindowCenterColumnWidth);
            rightColumn.Width = (GridLength)converter.ConvertFromString(Settings.Default.MainWindowRightColumnWidth);

            Trace.WriteLine(string.Format("LOADED Left: {0}, Center: {1}, Right {2}", leftColumn.Width, centerColumn.Width, rightColumn.Width));
        }
        catch (Exception)
        {
            // Fail silently, the worse case is we go with the defaults, it's going to be okay
        }
    }

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        base.OnClosing(e);

        //...

        try
        {
            GridLengthConverter converter = new GridLengthConverter();
            Settings.Default.MainWindowLeftColumnWidth = converter.ConvertToString(leftColumn.Width);
            Settings.Default.MainWindowCenterColumnWidth = converter.ConvertToString(centerColumn.Width);
            Settings.Default.MainWindowRightColumnWidth = converter.ConvertToString(rightColumn.Width);

            Trace.WriteLine(string.Format("SAVED Left: {0}, Center: {1}, Right {2}", Settings.Default.MainWindowLeftColumnWidth, Settings.Default.MainWindowCenterColumnWidth, Settings.Default.MainWindowRightColumnWidth));
        }
        catch (Exception)
        {
            // Fail silently, the worst case is we don't save a little something, it's going to be okay
        }
    }

E que todos os funcionou para mim.Então, eu estou indo para ir com ele!

EDITAR:Mais tarde eu fiz algumas requinte para evitar a "curiosidade" da coluna da direita ficar maior.Agora tenho tudo o painel de alterações de tamanho de ir para um manipulador de eventos:

    private void PanelSizeChanged(object sender, SizeChangedEventArgs e)
    {
        // In order to keep the resizing from losing proportionality, we'll force it to be proportional to the current size.
        // Otherwise the right panel edges up and up while the other two remain at their starting 200*/300* values.
        // And when that happens eventually resizing the window only resizes the right panel, not proportionately as it does at the start.
        leftColumn.Width = new GridLength(leftColumn.ActualWidth, GridUnitType.Star);
        centerColumn.Width = new GridLength(centerColumn.ActualWidth, GridUnitType.Star);
        rightColumn.Width = new GridLength(rightColumn.ActualWidth, GridUnitType.Star);
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top