绑定TextBox的高度属性

时间:2015-11-07 23:17:35

标签: c# wpf xaml 2-way-object-databinding

我需要将TextBox es的高度绑定到我的数据模型。每次TextBox调整大小时,都应更新模型。 TextBox已调整大小,因为它会将内容包装到MaxHeight,直到达到<Window x:Class="BindingTester.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:BindingTester" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Canvas> <TextBox Canvas.Left="234" Canvas.Top="71" Text="TextBox" TextWrapping="Wrap" ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="200" AcceptsReturn="True" Height="{Binding TextBoxHeight, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged/> </Canvas> 时,它会显示滚动条。我举了一个例子来证明我的问题。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private double textBoxHeight;

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        //TextBoxHeight = 100.0;
    }

    public double TextBoxHeight
    {
        get { return textBoxHeight; }
        set
        {
            if (value != textBoxHeight)
            {
                textBoxHeight = value;
                RaisePropertyChanged("TextBoxHeight");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

TextBoxHeight

当我使用它时,从源到目标的绑定工作正常。当我在MainWindow的构造函数中设置TextBox属性时,TextBox完美地调整为100,但是大小似乎是固定的。当我没有设置它时(因为高度为100,内容很大而且#34; TextBox&#34;)首先表现得像预期的那样:TextBoxHeight&#39 ; s大小适合内容。模型中的NaN更新为Height

我知道发生这种情况是因为NaN属性在未设置时返回ActualHeight,而是我必须要求TextBox。但无论如何,我认识到如果我输入一些文本(例如换行符)来调整Height TextBoxHeight的大小,IValueConverter属性仍然没有更新,并且设置者是没有再次调用...我也尝试使用ActualHeight使用TextBox更新它,但没有成功。

我知道在这个示例中,即使我通过输入换行符来调整TextBoxHeight的大小,NaN每次都会使用TextBox进行更新,但是第一次调用setter时SizeChanged已初始化。令我困惑的是,Binding似乎无法工作......我知道问题本身的解决方案:订阅DataContext事件,获取发件人对象的joinPoint.getTarget() 并手动设置模型。但我认为应该有一个解决方案,无需在代码隐藏中订阅和访问模型,只绑定属性。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

多次阅读您的问题后,我得出以下结论:您希望TextBoxHeight变量中的文本框的当前高度。如果添加更多文本,则希望TextBox高度更改,但只有当TextBox高度超过100时,滚动条才可见。

以下代码会在添加更多文本时增加TextBox的高度。如果减少文本,TextBox的高度将降低到MinHeight值。

    <TextBox x:Name="Tbx1"
            Width="219"          
            TextWrapping="Wrap"
            ScrollViewer.VerticalScrollBarVisibility="Auto" 
            MaxHeight="100"
            AcceptsReturn="True"
            MinHeight="{Binding TextBoxHeight, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            SizeChanged="Tbx1_SizeChanged"
     />

////////

private void Tbx1_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            TextBoxHeight = Tbx1.ActualHeight;
        }

如果我没有正确理解你的要求,请纠正我。

答案 1 :(得分:-1)

我可以建议您使用行为或其他事件来命令机制,然后您可以监听OnResizeAction事件来处理大小更改并将这些事件转换为您想要的任何逻辑。这是一个小例子。  1. Xaml代码:

<Window x:Class="SoResizeIssue.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:soResizeIssue="clr-namespace:SoResizeIssue"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <soResizeIssue:MainViewModel/>
</Window.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
             Text="{Binding ContentFromDataContext, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
        <i:Interaction.Behaviors>
            <soResizeIssue:ResizeHandlingBehavior OnResizeAction="{Binding OnResizeAction, UpdateSourceTrigger=PropertyChanged}"/>
        </i:Interaction.Behaviors>
    </TextBox>
</Grid></Window>

2。行为代码:

public class ResizeHandlingBehavior:Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SizeChanged += AssociatedObjectOnSizeChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.SizeChanged -= AssociatedObjectOnSizeChanged;
    }

    private void AssociatedObjectOnSizeChanged(object sender, SizeChangedEventArgs args)
    {
        var action = OnResizeAction;
        if(action == null) return;
        action(args);
    }

    public static readonly DependencyProperty OnResizeActionProperty = DependencyProperty.Register(
        "OnResizeAction", typeof (Action<object>), typeof (ResizeHandlingBehavior), new PropertyMetadata(default(Action<object>)));

    public Action<object> OnResizeAction
    {
        get { return (Action<object>) GetValue(OnResizeActionProperty); }
        set { SetValue(OnResizeActionProperty, value); }
    }
}

3。 ViewModel代码:

public class MainViewModel:BaseObservableObject
{
    private string _contentFromDataContext;
    private Action<object> _onResizeAction;

    public MainViewModel()
    {
        OnResizeAction = new Action<object>(InnerOnResizeAction);
    }

    private void InnerOnResizeAction(object obj)
    {
        var args = obj as SizeChangedEventArgs;
        //do you logic here
    }

    public string ContentFromDataContext
    {
        get { return _contentFromDataContext; }
        set
        {
            _contentFromDataContext = value;
            OnPropertyChanged();
        }
    }

    public Action<object> OnResizeAction
    {
        get { return _onResizeAction; }
        set
        {
            _onResizeAction = value;
            OnPropertyChanged();
        }
    }
} 

<强>更新  5.此解决方案将Resize的逻辑移动到ViewModel端,而TextBlock将由于Layout重新构建和实际大小更改而更改其大小。使用此解决方案,您不必对一些实际大小参数进行绑定,只需观察大小更改并将所有逻辑从窗口代码移到视图模型一侧,即窗口(xaml.cs)代码背后完全清楚。

  1. 还有另一种方法可以将事件触发器重定向到查看名为Trigger to Command pattern的模型,以下是链接:Binding WPF Events to MVVM ViewModel CommandsHow to trigger ViewModel command for a specific button eventsFiring a Command within EventTrigger of a style?
  2. 我希望它会对你有所帮助。 谢谢和问候,