使用MVVM/LINQ和XAML填充文本框

本文关键字:填充 文本 XAML MVVM LINQ 使用 | 更新日期: 2023-09-27 18:05:34

我想了解MVVM和LINQ,所以我设置了一个测试数据库。基于XAML的视图有一个单一的文本框-绑定到"组织名称"。然而,我一直在一个例子上工作,但我有"var结果"的麻烦(我认为)。

出于某种原因,我在标题"XamlParseException发生"下得到一个运行时错误,我认为这是查询字符串,而不是在字段中拉。

按照要求,完整的错误是:{"'调用类型'WpfApplication2上的构造函数。与指定绑定约束匹配的主窗口抛出了异常。行号"4",行位"9"。"}

public partial class MainWindow : Window
{
    private egwEntities db = new egwEntities();
    MyViewModel mvm = new MyViewModel();
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = mvm;
        var result = (from o in db.egw_addressbook select o).FirstOrDefault();
        if (result != null)
        {
            mvm.OrgName = result.org_name;
        }
    }
}
    public class MyViewModel
    {
         public string OrgName { get; set; }
    }
}
下面是我在视图中使用的XAMLI:
<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="EGW" Height="350" Width="525">
    <Grid>
        <TextBox Text="{Binding OrgName}" HorizontalAlignment="Left" Height="41" Margin="72,94,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="318"/>
    </Grid>
</Window>

使用MVVM/LINQ和XAML填充文本框

错误信息表明

var result = (from o in db.egw_addressbook select o).FirstOrDefault();
if (result != null) {
    mvm.OrgName = result.org_name;
}

失败,导致主窗口构造失败,给出XamlParse异常。您可以通过删除这些行来测试它,看看它是否运行。

MVVM
MVVM形状的目标之一是减少视图(窗口)和数据之间的链接。在上面的例子中,您从Model-View- viewmodel形状中丢失了模型(或者更确切地说,您已经合并了模型和视图)。

你可以这样试试。

将数据访问分离到存储库中—使测试更容易

public interface IRepository {
    IEnumerable<Organization> GetOrganizations();
}

我已经使用了一个虚拟存储库,您可以将其替换为您的DataContext代码

public IEnumerable<Organization> GetOrganizations() {
    return new[] {new Organization() {Name = "A name"}};
}

为应用程序添加一个模型

public class AppModel {
    public AppModel(IRepository repository) {
        var result = (from o in repository.GetOrganizations() select o).FirstOrDefault();
        if (result != null) {
            OrgName = result.Name;
        } 
    }
    public string OrgName { get; private set; }
}

说明:
这可以通过几种方式实现。我们倾向于有非常薄的ViewModel,在ViewModel和model之间有很多成员复制(例如,组织名称出现在两者中);ViewModels主要是传递和格式化。这不是唯一的方法(甚至可能不是最好的)。我将在MVVM形状上进行网络搜索以跟踪

我稍微调整了一下视图模型代码。如果不写入组织名,则应设置为只读

public class MainWindowViewModel {
    private readonly AppModel _model;
    public MainWindowViewModel(AppModel model) {
        _model = model;
    }
    public string OrgName {
        get { return _model.OrgName; }
    }
}

如果组织名称是只读的,那么绑定需要是单向的。添加数据上下文定义有助于查找绑定错误。

<Window x:Class="Sus.ProofsOfConcept.SimpleMvvm.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:views="clr-namespace:MyExamples.SimpleMvvm"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance views:MainWindowViewModel, IsDesignTimeCreatable=false }"
    Title="EGW" Height="350" Width="525">
<Grid>
    <TextBox Text="{Binding OrgName, Mode=OneWay}" HorizontalAlignment="Left" Height="41" Margin="72,94,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="318"/>
</Grid>
</Window>

默认的运行机制(在App.Xaml中命名的启动窗口)不再工作,如果没有依赖注入(DI),你可以使用

public partial class App : Application {
    protected override void OnStartup(StartupEventArgs e) {
        var model = new AppModel(new Repository());
        var viewModel = new MainWindowViewModel(model);
        var view = new MainWindow() {DataContext = viewModel};
        view.Show();
    }
}

该错误与您的XAML有关,如果您有语法错误,它将抛出运行时错误。如果您的var result行有问题,您可能会收到一些其他错误。

试着把你的textrap行改成这样:

TextWrapping=TextWrapping.Wrap