【问题标题】:WPF How to make RichTextBox width follow that of the parent control?WPF 如何使 RichTextBox 的宽度跟随父控件的宽度?
【发布时间】:2018-03-06 03:01:30
【问题描述】:

这里我有以下简单的窗口:

上面是一个DataGrid,下面是一个TextBox。窗口的大小设置为内容的宽度。这是所需的布局。

现在我需要显示一些富文本,因此我将 TextBox 替换为 RichTextBox。问题是现在窗口延伸到屏幕的宽度,就像这样(我当然把它缩小了,但你明白了):

我已经尝试将 RichTextBox 的宽度绑定到父级的实际宽度:

 <RichTextBox Width="{Binding ElementName=Wrapper, Path=ActualWidth}"/>

但它仍会扩展到整个窗口。顺便说一句,如果我在上面的代码中使用 TextBox,也会发生同样的情况。

如何使 RichTextBox 的宽度适合父级,同时仍保持动态窗口布局?我的意思是 DataGrid 是窗口宽度和 RichTextBox 宽度都必须服从的关键元素。

以下是完整代码。

XAML

<Window x:Class="RichTextBox_Wrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RichTextBox_Wrap"
        mc:Ignorable="d"
        SizeToContent="Width"
        Title="MainWindow" Height="250" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <DataGrid Grid.Row="0" 
                  HeadersVisibility="Column" 
                  CanUserAddRows="False"
                  ItemsSource="{Binding Items}">
        </DataGrid>
        <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Text="Info" />
        </StackPanel>
        <DockPanel x:Name="Wrapper" Grid.Row="2">
            <Border BorderBrush="CadetBlue" BorderThickness="1">
                <RichTextBox />
            </Border>
        </DockPanel>
    </Grid>
</Window>

C#

public class Item
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public double Price { get; set; }
    }

    public class ViewModel
    {
        public ObservableCollection<Item> Items { get; set; }

        public ViewModel()
        {
            Items = new ObservableCollection<Item>
            {
                new Item {Name = "Apple", Description="Fruit", Price=3},
                new Item {Name = "Banana", Description="Fruit", Price=5},
                new Item {Name = "Tomato", Description="Vegetable", Price=4},
            };
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModel();
        }
    }

解决方案

1. mm8 的解决方案几乎可以工作,但似乎 Loaded 事件发生在早期以正确计算 ActualWidth - RichTextBox 不填充宽度并留下间隙。但更进一步,我使用窗口的“Content_Rendered”事件来修复窗口的宽度,然后将 RichTextBox 的宽度设置为自动。

<RichTextBox x:Name="RichBox" Grid.Row="1" MinHeight="75" Width="0" Visibility="Hidden" />

private void Window_ContentRendered(object sender, EventArgs e)
{
    var window = sender as Window;
    window.SizeToContent = SizeToContent.Manual;
    window.Width = window.ActualWidth;
    RichBox.Width = double.NaN;
    RichBox.Visibility = Visibility.Visible;
}

2. Spongebrot 是正确的。实际上,当移除额外边框时,绑定到父级的 ActualWidth 有效。但在现实生活中,我的控制更加复杂,边界的存在是有原因的。但这可以通过级联绑定来解决:

<DockPanel x:Name="Wrapper" Grid.Row="2" >
    <Border x:Name="MyBorder" BorderBrush="CadetBlue" BorderThickness="1" Width="{Binding ElementName=Wrapper, Path=ActualWidth}" >
        <RichTextBox x:Name="RichBox" Width="{Binding ElementName=MyBorder, Path=Width}" />
    </Border>
</DockPanel>

如果绑定到祖父母或更远的祖先,绑定到 ActualWidth 似乎无法正常工作。这似乎就是为什么 Sinatr 的建议也不起作用的原因。

【问题讨论】:

  • 我不明白你的问题是你应该能够用default layout做到这一点
  • 检查您的 RichTextBox 是否有一定的高 MinWidth。也许如果您降低该值,它不会拉伸窗口?
  • 不应该是Dock的边界到DockPanel吗?尝试将属性DockPanel.Dock=Left 添加到您的边框,看看您是否得到了您想要的。
  • ActualWidth 绑定的问题似乎是边框的 BorderThickness。如果您直接在 RichtTextBox 控件上设置边框,则绑定到 Wrapper 的 ActualWidth 似乎有效。

标签: c# wpf richtextbox sizetocontent


【解决方案1】:

一个简单的解决方法是在 XAML 标记中将 RichTextBoxWidth 设置为 0,然后处理其 Loaded 事件并在加载后将 Width 设置为窗口的宽度:

<RichTextBox Width="0" Loaded="RichTextBox_Loaded" />

private void RichTextBox_Loaded(object sender, RoutedEventArgs e)
{
    RichTextBox rtb = sender as RichTextBox;
    rtb.Width = this.Width;
}

【讨论】:

    【解决方案2】:

    SizeToContent="宽度"

    所以您希望窗口自动调整为DataGrid 宽度?

    RichTextBox 看起来很特别,它会从其父容器请求最大的可用空间,随意占据整个组合桌面的宽度。一个简单的解决方法是限制它的宽度:

    <Grid>
        <DataGrid x:Name="dataGrid" />
        <DockPanel>
            <Border>
                <RichTextBox Width="{Binding ActualWidth, ElementName=dataGrid}" />
            </Border>
        </DockPanel>
    </Grid>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2023-01-03
      • 2015-04-14
      • 2018-11-14
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多