Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET 3.5 | WPF Textbox在绑定到视图模型属性时拒绝更新自身_C#_Wpf_.net 3.5 - Fatal编程技术网

C# .NET 3.5 | WPF Textbox在绑定到视图模型属性时拒绝更新自身

C# .NET 3.5 | WPF Textbox在绑定到视图模型属性时拒绝更新自身,c#,wpf,.net-3.5,C#,Wpf,.net 3.5,在我开始解释我的问题之前,请注意我的目标框架是.NET3.5 我有一个文本框,其文本绑定到viewmodel属性。我的要求是,当用户(通过键盘和鼠标粘贴)在文本框中输入内容时,应清除其中的任何垃圾字符,并用替换的字符串更新文本框[在下面的示例中,用“h”替换“s”) XAMLCode: <Style x:Key="longTextField" TargetType="{x:Type TextBoxBase}"> <Setter Property="Sn

在我开始解释我的问题之前,请注意我的目标框架是.NET3.5

我有一个文本框,其文本绑定到viewmodel属性。我的要求是,当用户(通过键盘和鼠标粘贴)在文本框中输入内容时,应清除其中的任何垃圾字符,并用替换的字符串更新文本框[在下面的示例中,用“h”替换“s”)

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>
以上这些根本不适合我。视图模型属性设置程序正在启动…值正在被替换..但是文本框没有得到更新。令人困惑的是,它在.Net4.0上运行得非常好

除了升级到.NET4.0之外,您知道为什么这不起作用,以及解决这个问题的潜在方法是什么吗

我的要求:

  • 用户可以在多行文本框中键入和粘贴任何内容

  • 文本可能包含垃圾,在它出现在文本框之前应该进行更改

提前感谢,,
-Mike

我遇到了一个非常类似的问题,我想要双向绑定,我修改了ViewModel中的值,希望在文本框中看到更新。我能够解决它。虽然我使用的是.NET4.0,但基本上我也遇到了同样的问题,因此这可能也值得在3.5中尝试一下

简短答复: 我遇到的是一个bug,
TextBox的
显示的文本与该
TextBox的
own
text
属性的值不同步。我了解了这一点,并且能够通过VisualStudio2010中的调试器以及Meleak的
TextBlock
技术验证这一点

我能够通过使用显式绑定解决它。这需要处理
UpdateSource()
UpdateTarget()
问题,以代码隐藏(或者像我最终做的那样,以使其更易于重用的自定义控制代码)

进一步解释: 下面是我如何处理显式绑定任务的。首先,我有一个TextChanged事件的事件处理程序,它更新了绑定的源:

// Push the text in the textbox to the bound property in the ViewModel
textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
其次,在中,我为TextBox的已加载事件提供了一个事件处理程序。在该处理程序中,我为我的ViewModel的PropertyChanged事件注册了一个处理程序(ViewModel在这里是“DataContext”):

最后,在PropertyChanged处理程序中,我使TextBox从ViewModel中获取值(通过启动UpdateTarget())这会使文本框从ViewModel中获取修改后的字符串(在您的示例中是带有替换字符的字符串)。在我的例子中,我还必须在刷新文本后(从UpdateTarget()恢复用户的插入符号位置)。这一部分可能适用于你的情况,也可能不适用于你的情况

    /// <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;
        }

    }
//
///使用VM中的值更新文本框文本。
/// 
void ViewModel\u PropertyChanged(对象发送方,System.ComponentModel.PropertyChangedEventArgs e)
{
//此文本框只关心它绑定到的属性
if(e.PropertyName!=MyViewModel.ValueStrPropertyName)
返回;
//这里的“this”指的是实际的文本框,因为我在自定义控件中
//这源于文本框
BindingExpression bindingExp=this.GetBindingExpression(TextBox.TextProperty);
//ViewModel的版本(用户字符串的可能修改版本)
字符串viewModelValueStr;
viewModelValueStr=(bindingExp.DataItem作为MyViewModel);
if(viewModelValueStr!=this.Text)
{
//存储用户的旧插入符号位置(相对于str的末端),以便我们可以恢复它
//从ViewModel的相应属性更新文本后。
int oldCaretFromEnd=this.Text.Length-this.CaretIndex;
//使文本框的文本从ViewModel中获取更新的值
这个.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
//还原用户的插入符号索引(相对于str的结尾)
this.CaretIndex=this.Text.Length-oldCaretFromEnd;
}
}

我遇到了一个非常类似的问题,我想要双向绑定,我修改了ViewModel中的值,希望在文本框中看到更新。我能够解决它。虽然我使用的是.NET4.0,但基本上我也遇到了同样的问题,因此这可能也值得在3.5中尝试一下

简短答复: 我遇到的是一个bug,
TextBox的
显示的文本与该
TextBox的
own
text
属性的值不同步。我了解了这一点,并且能够通过VisualStudio2010中的调试器以及Meleak的
TextBlock
技术验证这一点

我能够通过使用显式绑定解决它。这需要处理
UpdateSource()
UpdateTarget()
问题,以代码隐藏(或者像我最终做的那样,以使其更易于重用的自定义控制代码)

进一步解释: 下面是我如何处理显式绑定任务的。首先,我有一个TextChanged事件的事件处理程序,它更新了绑定的源:

// Push the text in the textbox to the bound property in the ViewModel
textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
其次,在中,我为TextBox的已加载事件提供了一个事件处理程序。在该处理程序中,我为我的ViewModel的PropertyChanged事件注册了一个处理程序(ViewModel在这里是“DataContext”):

最后,在PropertyChanged处理程序中,我使TextBox从ViewModel中获取值(通过启动UpdateTarget())这会使文本框从ViewModel中获取修改后的字符串(在您的示例中是带有替换字符的字符串)。在我的情况下,我还必须处理r
    /// <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;
        }

    }