.NET 3.5 | WPF文本框拒绝自我更新,同时绑定到一个视图模型属性 [英] .NET 3.5 | WPF Textbox refuses to update itself while binded to a view model property

查看:120
本文介绍了.NET 3.5 | WPF文本框拒绝自我更新,同时绑定到一个视图模型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我开始解释我的问题,请注意,我的目标框架是.NET 3.5。

Before I start explaining my issue, please note that my target framework is .NET 3.5.

我有一个文本框的文本绑定到一个视图模型属性。我的要求是,当用户输入了一些(通过键盘和鼠标粘贴)插入文本框,它里面的任何垃圾字符进行清洗和文本框应与替换字符串[在下面的例子中的更新到被替换与H。

I have a textbox whose text is bound to a viewmodel property. My requirement is that when user enters something(via keyboard as well as Mouse Paste) into the textbox, any junk characters inside it should be cleaned and the textbox should be updated with the replaced string[In the below example 's' to be replaced with 'h'].

XAML code:

XAMLCode:

 <Style x:Key="longTextField" TargetType="{x:Type TextBoxBase}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="AcceptsReturn" Value="True"/>
            <Setter Property="AllowDrop" Value="true"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border      
                      Name="Border"    
                      Padding="2"    
                      Background="Transparent"    
                      BorderBrush="LightGray"    
                      BorderThickness="1">
                            <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="Black"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"  MinLines="3"       TextWrapping="Wrap"
                 SpellCheck.IsEnabled="True" Style="{StaticResource longTextField}"></TextBox>

视图模型属性:

ViewModel property:

     private string _value;
            public string Value
            {
                get
                {
                    return _value;
                }
                set
                {
                    if (_value == value) 
                        return;

                    _value = value;
//replaces 's' with 'h' and should update the textbox.
                    _value = _value.Replace('s','h');
                    RaisePropertyChanged(() => Value);
                }
            }

以上是根本就没有为我工作。视图模型属性设置器发射......的价值越来越replaced..however文本框是不会得到更新。什么是令人困惑的是,这个工程完全可以在.Net4.0。

The above is simply not working for me. The view model property setter is firing...the value is getting replaced..however the textbox is not getting updated. What is confusing is that this works perfectly on .Net4.0.

你知道为什么这不会工作,哪些是潜在的解决方案,当然这个问题,除了升级到.NET 4.0?

Do you know why this wont work and what is a potential solution to this problem, of course other than upgrading to .NET 4.0?

我的要求:

  • 用户可以输入并粘贴到任何一个multilined文本框。

  • User can type as well as paste anything into a multilined textbox.

该文本可包含的垃圾应该被改变后,才到文本框。

The text can contain junk which should be changed before it comes on to the textbox.

在此先感谢, -Mike

Thanks in advance, -Mike

推荐答案

我遇到了一个非常类似的问题,我想这两个结合的方式,我是修改视图模型的价值,并希望看到在文本框中的更新。我能够把它解决。虽然我是用.NET 4.0,我基本上有同样的问题,所以这可能是值得尝试与3.5的情况也是如此。

I encountered a very similar problem where I wanted the two way binding and I was modifying the value in the ViewModel and expecting to see the update in the TextBox. I was able to get it resolved. Although I was using .NET 4.0, I basically had the same issue, so this may be worth trying out for your situation with 3.5 as well.

我遇到了一个错误,其中文本框的显示的文字越来越不同步的,该值文本框的文本属性。 Meleak的回答避让我在这个类似的问题,我可以验证这一点与调试器在Visual Studio 2010中,以及采用Meleak的的TextBlock 技术。

What I encountered was a bug where the TextBox's displayed text was getting out of sync with the value of that TextBox's own Text property. Meleak's answer to a similar question clued me in to this and I was able to verify this with the debugger in Visual Studio 2010, as well as by employing Meleak's TextBlock technique.

我能够通过使用显式绑定以解决这个问题。这需要处理 UpdateSource() UpdateTarget()发出自己在code的后面(或自定义控制code,因为我最终没有使它更易于重复使用)。

I was able to resolve it by using explicit binding. This required handling the UpdateSource() and UpdateTarget() issues myself in code behind (or in a custom control code as I eventually did to make it easier to reuse).

下面是我如何处理的显式绑定的任务。首先,我有一个事件处理TextChanged事件而更新绑定源:

Here's how I handled the explicit binding tasks. First, I had an event handler for the TextChanged event which updated the source of the binding:

// Push the text in the textbox to the bound property in the ViewModel
textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

二,我有一个事件处理文本框的Loaded事件。在该处理程序,我注册了一个处理程序为我的视图模型的PropertyChanged事件(视图模型是DataContext的在这里):

Second, in I had an event handler for the TextBox's Loaded event. In that handler, I registered a handler for the PropertyChanged event of my ViewModel (the ViewModel was the "DataContext" here):

private void ExplicitBindingTextBox_Loaded(object sender, RoutedEventArgs e)
{
    TextBox textBox = sender as TextBox;

    if (textBox.DataContext as INotifyPropertyChanged == null)
        throw new InvalidOperationException("...");

    (textBox.DataContext as INotifyPropertyChanged).PropertyChanged +=
                  new PropertyChangedEventHandler(ViewModel_PropertyChanged);
}

最后,在的PropertyChanged处理程序中,我使文本框来抓住从视图模型的值(由启动UpdateTarget())。 这使得文本框您可以通过视图模型(在你的情况之一,替换的字符)修改后的字符串。在我来说,我也不得不处理刷新文本之后恢复用户的插入位置(从UpdateTarget())。这部分可能会或可能不适用于虽然你的情况。

Finally, in the PropertyChanged handler, I cause the TextBox to grab the value from the ViewModel (by initiating the UpdateTarget()). This makes the TextBox get the modified string from the ViewModel (in your case the one with replaced characters). In my case I also had to handle restoring the user's caret position after refreshing the text (from the UpdateTarget()). That part may or may not apply to your situation though.

    /// <summary>
    /// Update the textbox text with the value that is in the VM.
    /// </summary>
    void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        // This textbox only cares about the property it is bound to
        if (e.PropertyName != MyViewModel.ValueStrPropertyName)
            return;

        // "this" here refers to the actual textbox since I'm in a custom control
        //  that derives from TextBox
        BindingExpression bindingExp = this.GetBindingExpression(TextBox.TextProperty);
        // the version that the ViewModel has (a potentially modified version of the user's string)
        String viewModelValueStr;

        viewModelValueStr = (bindingExp.DataItem as MyViewModel).ValueStr;


        if (viewModelValueStr != this.Text)
        {
            // Store the user's old caret position (relative to the end of the str) so we can restore it
            //  after updating the text from the ViewModel's corresponding property.
            int oldCaretFromEnd = this.Text.Length - this.CaretIndex;

            // Make the TextBox's Text get the updated value from the ViewModel
            this.GetBindingExpression(TextBox.TextProperty).UpdateTarget();

            // Restore the user's caret index (relative to the end of the str)
            this.CaretIndex = this.Text.Length - oldCaretFromEnd;
        }

    }

这篇关于.NET 3.5 | WPF文本框拒绝自我更新,同时绑定到一个视图模型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆