双向绑定:在模型设置器中编辑XAML控件的传递值不会更新控件

时间:2016-05-20 07:39:33

标签: c# xaml mvvm windows-10 uwp

这适用于Windows 10 Universal App。

XAML:

<RelativePanel Padding="4" Margin="4,12,0,0">
     <TextBlock x:Name="Label" Text="Class Name" Margin="12,0,0,4"/>
       <ListView x:Name="ClassTextBoxes" 
                 ItemsSource="{Binding TextBoxList}" 
                 SelectionMode="None" RelativePanel.Below="Label">
            <ListView.ItemTemplate>
              <DataTemplate >
                <RelativePanel>
                  <TextBox x:Name="tbox" 
                       PlaceholderText="{Binding PlaceHolder}" 
                       Text="{Binding BoxText, 
                       Mode=TwoWay,
                       UpdateSourceTrigger=PropertyChanged}" 
                       Padding="4" Width="200" MaxLength="25"/>
                  <TextBlock x:Name="errorLabel" 
                       RelativePanel.Below="tbox"
                       Text="{Binding Error, Mode=TwoWay}"
                       Padding="0,0,0,4"
                       FontSize="10" 
                       Foreground="Red"/>
                  <Button Content="Delete" Margin="12,0,0,0" RelativePanel.RightOf="tbox"/>
              </RelativePanel>
            </DataTemplate>
          </ListView.ItemTemplate>
       </ListView>
</RelativePanel>

型号:

public class TextBoxStrings : BaseModel
{
    private string _placeholder;
    public string PlaceHolder
    {
        get { return _placeholder; }
        set
        {
            if (_placeholder != value)
            {
                _placeholder = value;
                NotifyPropertyChanged();
            }
        }
    }
    private string _boxText;
    public string BoxText
    {
        get { return _boxText; }
        set
        {
            if (_boxText != value)
            {
                _boxText = CheckBoxText(value);
                NotifyPropertyChanged();
            }
        }
    }

    public string CheckBoxText(string val)
    {
        var r = new Regex("[^a-zA-Z0-9]+");
        return r.Replace(val, "");
    }
}

视图模型:

private TrulyObservableCollection<TextBoxStrings> _textBoxList;
public TrulyObservableCollection<TextBoxStrings> TextBoxList
{
        get { return _textBoxList; }
        set
        {
            if (_textBoxList != value)
            {
                _textBoxList = value;
                RaisePropertyChanged();
            }
        }
}

我在视图模型中向我的TextBoxString集合添加了新的TextBoxList个对象。

  

我想让用户无法键入某些字符(或者更确切地说,只要它们被删除,它们就会被删除   输入。

这在模型中有效。设置断点并查看值,模型中的所有内容都正常工作:值进入设置器并进行更改,_boxText保存从CheckBoxText();

设置的新值

但问题是,在我的视图中,文本框不会反映我在模型中对基础文本所做的更改。

因此,如果我在“tbox”中键入“abc *()”,则模型中的值将为“abc”。但是,文本框的值仍为“abc *()”。

我觉得这与我正在编辑集合内部的项目并且我没有任何实现来处理集合中的更改项目这一事实有关。我的印象是,使用INotifyPropertyChangedObservableCollection<T>会照顾我。

有人有任何建议吗?

谢谢!

编辑:所以,现在我正在尝试使用TrulyObservableCollection,因为我认为这是问题,但它没有帮助。这是:https://gist.github.com/itajaja/7507120

3 个答案:

答案 0 :(得分:0)

您应该编辑nav,然后将选中的值发送到UI。只需将BoxText发送至value,然后将已经编辑的分配给CheckBoxText。然后,您应该通过调用_boxTextBoxText发送到用户界面。请参阅以下代码段:

RaisePropertyChanged("BoxTest")

对于放置在集合中的属性的一个属性,使用private string _boxText; public string BoxText { get { return _boxText; } set { if (_boxText != value) { _boxText=CheckBoxText(value); RaisePropertyChanged("BoxText"); } } } 的位置没有区别。包含馆藏和INotifyPropertyChanged can be seen here

的完整示例

答案 1 :(得分:0)

if (_boxText != value)
{
    _boxText = CheckBoxText(value);
    NotifyPropertyChanged();
}

尝试将其更改为:

var tmp = CheckBoxText(value);
if (_boxText != tmp)
{
    _boxText = tmp;
    NotifyPropertyChanged();
}

我希望,在您的XAML中,对属性BoxText的绑定是two-way,对吧?

答案 2 :(得分:0)

  

但问题是,在我的视图中,文本框并不反映我在模型中创建的基础文本的更改。

正如您所见,TextBox确实反映了您模型的变化。当你输入&#34; abc *()&#34;在TextBox中,模型中的值将更改为&#34; abc&#34;。这里的问题是UWP中的绑定系统是智能的&#34;。对于 TwoWay 绑定,对目标的更改将自动传播到,在此方案中,绑定系统会假定将触发PropertyChanged事件源中的相应属性,它忽略这些事件。因此,即使您在源代码中有RaisePropertyChangedNotifyPropertyChanged,TextBox仍然无法更新。

在WPF中,我们可以调用BindingExpression.UpdateTarget Method来强制更新。但是这种方法在UWP中不可用。

作为解决方法,您应该能够使用TextBox.TextChanged event检查输入,如下所示:

private void tbox_TextChanged(object sender, TextChangedEventArgs e)
{
    var tb = sender as TextBox;
    if (tb != null)
    {
        var originalText = tb.Text;

        var r = new Regex("[^a-zA-Z0-9]+");
        if (originalText != r.Replace(originalText, ""))
        {
            var index = (tb.SelectionStart - 1) < 0 ? 0 : (tb.SelectionStart - 1);
            tb.Text = r.Replace(originalText, "");
            tb.SelectionStart = index;
        }
    }
}

然而,它可能会破坏您的MVVM模型,您可以使用数据验证来避免这种情况,这里有一个博客:Let’s Code! Handling validation in your Windows Store app (WinRT-XAML)您可以参考。而就我个人而言,数据验证是这种情况的更好方向。