用于虚拟对象的UWP MVVM数据绑定(来自String的textbox.text)

时间:2016-08-15 05:12:19

标签: c# mvvm data-binding uwp

好吧,使用UWP模板10进入MVVM。我已经阅读了很多页面,虽然每个人都试图说它非常简单,但我仍然无法使其工作。

要将其置于上下文中,OCR正在图像上运行,我希望文本自动显示在文本框中。

这是我的模特:

public class TextProcessing
{
    private string _ocrText;
    public string OcrText
    {
        get { return _ocrText; }
        set
        {
            _ocrText = value;
        }
    }
}

这是我的ViewModel:

public class ScanPageViewModel : ViewModelBase, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private TextProcessing _ocrTextVM;
    public ScanPageViewModel()
    {
        _ocrTextVM = new TextProcessing();
    }

    public TextProcessing OcrTextVM
    {
        get { return _ocrTextVM; }
        set {
            _ocrTextVM = value;
            this.OnPropertyChanged("OcrTextVM");
            }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

这是我的观点:

<TextBox x:Name="rtbOcr" 
       Text="{Binding OcrTextVM.OcrText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 

首先,这不起作用。有人可以尝试显示我出错的地方吗?

然后,数据来自服务文件,服务如何更新该值?什么是正确的代码?

提前致谢。

3 个答案:

答案 0 :(得分:2)

以下代码来自code.msdn(How to achieve MVVM design patterns in UWP),对您有所帮助:

逐步检查代码。

1.ViewModel实现了接口INotifyPropertyChanged,并在属性set方法中调用了PropertyChanged,如下所示:

public sealed class MainPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _productName;
    public string ProductName
    {
        get { return _productName; }
        set
        {
            _productName = value;
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(ProductName)));
            }
        }
    }
}

2.在您的页面中初始化ViewMode,并将DataContext设置为ViewMode,如下所示:

public sealed partial class MainPage : Page
{
    public MainPageViewModel ViewModel { get; set; } = new MainPageViewModel();
    public MainPage()
    {
        ...
        this.DataContext = ViewModel;
    }
}

3.在你的xaml中,绑定来自viewMode的数据,如下所示:

<TextBox Text="{Binding Path=ProductName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Name="ProductNameTextBox" TextChanged="ProductNameTextBox_TextChanged" />

答案 1 :(得分:1)

由于您将构造函数中的值设置为其支持字段并绕过该属性,因此您的OnPropertyChanged调用OcrTextVM实际上并未在您的情况下调用。

如果您通过属性设置值,它应该有效:

public ScanPageViewModel()
{
    OcrTextVM = new TextProcessing();
}

当然,您的视图需要知道ScanPageViewModel是其DataContext。最简单的方法是在您的视图的代码隐藏的构造函数中:

public OcrView()
{
    DataContext = new ScanPageViewModel();
    InitializeComponent();
}

假设你的OCR服务在使用时返回一个新的TextProcessing对象,设置OcrTextVM的属性就足够了:

public class ScanPageViewModel : ViewModelBase, INotifyPropertyChanged
{
    //...       
    private void GetOcrFromService()
    {
        //...
        TextProcessing value = OcrService.Get();
        OcrTextVM = value;  
    }
}

在注释中,OcrTextVM名称并不能真正反映该属性正在做什么,因为它看起来并不像是一个视图模型。考虑重命名它。

答案 2 :(得分:1)

实际上,一旦我理解了,这很容易。这是更新TextBox.Text

所需的代码

在模特中:

public class DisplayText : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
        }
    }
}

在XAML文件中:

<TextBox Text="{Binding Helper.Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ... />

在ViewModels中:

    private DisplayText _helper = new DisplayText();
    public DisplayText Helper
    {
        get { return _helper; }
        set
        {
            _helper = value;
        }
    }

然后来自ViewModels的任何mod:

Helper.Text = "Whatever text, or method returning a string";