基本WPF布局问题

时间:2010-12-01 01:08:23

标签: wpf debugging

我正在学习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 个答案:

答案 0 :(得分:2)

  

我绑定的方式好吗?

它可能会奏效,但这不是最佳做法。最佳实践是使用实际数据绑定。首先,您需要将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>

并将其分配给DataTemplate中的TextBox:

<TextBox IsReadOnly="true" ... Text="{Binding ErrorMessage}"
         Style="{StaticResource hoverTextBox}" />