Основной вопрос по макету WPF - PullRequest
2 голосов
/ 01 декабря 2010

Я изучаю WPF и пытаюсь следовать какой-то передовой практике. Я сейчас немного потерян и мне нужно какое-то направление.

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

<Window x:Class="ErrorLog.UI.WPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="800" Width="1200" Loaded="Window_Loaded">

<StackPanel Name="mainContainer">
    <StackPanel Orientation="Horizontal" Name="Menu">
        <Button Name="Refresh">Refresh</Button>
    </StackPanel>        
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <StackPanel Name="errorMessagePlaceHolder"></StackPanel>
    </ScrollViewer>
</StackPanel>

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

private void LoadData()
    {
        IErrorLogReader errorLogReader = new ErrorLogReader();
        var errors = errorLogReader.RetrieveErrors();

        if (errors.Count == 0)
        {
            TextBox noErrors = new TextBox();
            noErrors.Text = "No errors found";
            errorMessagePlaceHolder.Children.Add(noErrors);
        }
        else
        {
            for (var i = errors.Count - 1; i > 0; i--)
            {
                TextBox errorMessage = new TextBox();

                errorMessage.IsReadOnly = true;
                errorMessage.Padding = new Thickness(10);

                errorMessage.Text = errors[i].ErrorMessage;
                errorMessage.TextWrapping = TextWrapping.Wrap;

                errorMessage.MouseEnter += ErrorMessageMouseEnter;
                errorMessage.MouseLeave += ErrorMessageMouseLeave;

                errorMessagePlaceHolder.Children.Add(errorMessage);
            }
        }
    }

    protected void ErrorMessageMouseEnter(object sender, RoutedEventArgs e)
    {
        ((TextBox) sender).Background = Brushes.AntiqueWhite;
    }

    protected void ErrorMessageMouseLeave(object sender, RoutedEventArgs e)
    {
        ((TextBox) sender).Background = null;
    }

Итак, первое, что я хочу знать:

  • Хорошо, как я связываюсь?
  • Полоса прокрутки отключена
  • Плохо, как я делаю эффект наведения мыши?

Приветствие.

1 Ответ

2 голосов
/ 01 декабря 2010

Хорошо, как я связываюсь?

Это может сработать, но это не лучшая практика. Лучшая практика - использовать фактическую привязку данных. Во-первых, вам нужно заменить вашу StackPanel чем-то, что можно привязать к списку. ItemsControl - это вещь, наиболее близкая к простой StackPanel, другие варианты, например, ListBox.

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <ItemsControl Name="errorMessageList" />
</ScrollViewer>
private void LoadData()
{
    IErrorLogReader errorLogReader = new ErrorLogReader();
    var errors = errorLogReader.RetrieveErrors();

    errorMessageList.ItemsSource = errors;
}

Чтобы указать , как вы хотите отображать сообщения об ошибках, вы можете установить шаблон для ItemsControl:

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <ItemsControl Name="errorMessageList">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox IsReadOnly="true" ... Text="{Binding ErrorMessage}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</ScrollViewer>

Полоса прокрутки отключена

Вы вкладываете ScrollViewer в StackPanel ... это не сработает: StackPanel занимает столько места по вертикали, сколько ему нужно, поэтому ScrollViewer будет всегда иметь достаточно места и никогда не будет отображать прокрутку бар. Вам необходимо заменить StackPanel верхнего уровня на что-то, занимающее столько места, сколько доступно ; DockPanel, например:

<DockPanel Name="mainContainer">
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Name="Menu">
        <Button Name="Refresh">Refresh</Button>
    </StackPanel>        
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <StackPanel Name="errorMessagePlaceHolder"></StackPanel>
    </ScrollViewer>
</StackPanel>

Плохо ли мне делать эффект наведения мыши?

Это можно сделать с помощью стиля и триггера. Определите следующий стиль:

<Window ...>
    <Window.Resources>
        <Style x:Key="hoverTextBox" TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="AntiqueWhite" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    ...
</Window>

и назначьте его вашему TextBox внутри DataTemplate:

<TextBox IsReadOnly="true" ... Text="{Binding ErrorMessage}"
         Style="{StaticResource hoverTextBox}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...