首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVVM ViewModel在ViewModel中

MVVM ViewModel在ViewModel中
EN

Stack Overflow用户
提问于 2015-10-24 07:13:12
回答 2查看 2.7K关注 0票数 0

我正在尝试将现有的Windows表单软件转换为MVVM/WPF。我是MVVM的新手,所以我会犯很多错误。

在那个应用程序中,这些是我简化的主要对象:

product类,该类保存了每个不同产品的信息。而且,可以有许多相同UPC的产品,但是每个物理项都有一个唯一的标识符,比如UPC-date-serial,所以这个唯一标识符保存在products中的一个列表中。

代码语言:javascript
复制
class Product
{
    // This is the barcode of the product
    public UPC
    { get; set; }

    // This is a list which contains the unique ID of every product 
    public List<string> ProductSerialCodes
    { get; set; }

}

这样,如果我们拥有相同UPC的10个产品,那么我们就有一个产品类的一个实例,其中包含ProductSerialCodes列表中的10个项。

然后,在容器类中,这个类是标识每一个填充了产品的物理盒。一个盒子可以包含不同的产品。

代码语言:javascript
复制
class Container
{
    // The box Id
    public string ContainerID
    { get; set; }

    // The list of products in the box
    public List<Product> ProductList
    { get; set; } 
}

这些类有更多的代码和自我验证的函数,所以我认为最好将它们设置为ViewModels。

ProductViewModel:

代码语言:javascript
复制
class ProductViewModel
{
    List<string> _productSerialCodes = new List<string>();

    public string UPC
    { get; set; }

    public List<string> ProductSerialCodes
    { get { return _productSerialCodes; } }

    public int ItemsCount
    { get { return _productSerialCodes.Count; } }

    public AddItem(string itemID)
    {
        _productSerialCodes.Add(itemID);
        OnPropertyChanged("ItemsCount");
    }
}

*注意: AddItem()方法是从后台线程调用的。

ContainerViewModel:

代码语言:javascript
复制
public class ContainerViewModel
{
    private ObservableCollection<ProductViewModel> _productList;

    public ObservableCollection<ProductViewModel> ProductList
    { get { return _productList; } }

    public string ContainerID
    { get; set; }

    public AddItem(string itemID)
    {
        // This comes from a background thread.
        // I find the product related to the item,         
        // (If the product doesn't exist in the list I create it)
        _productList.Find(product).AddItem(itemId);
    }
}

这就是我使用MVVM的方法,我的MainViewModel有一个ContainerViewModel,我想在屏幕上显示产品列表和数量,例如:

代码语言:javascript
复制
UPC          Qty
000000000000 12

由于数据来自后台线程,因此必须由INotifyPropertyChanged自动更新。

我注意到的另一件事是,我需要单击窗口中的某个地方,以便UI更新。在阅读了一些博客之后,我发现使用SynchronizationContext对象可以解决这个问题:

然后当OnPropertyChanged(propertyName)被调用时,我称之为

代码语言:javascript
复制
SynchronizationContext _syncContext;
_syncContext.Post(delegate { CommandManager.InvalidateRequerySuggested(); }, null);

但是,只有当我在UI线程上进行测试时,这才能起作用。在我的新应用程序中,由于数据来自后台线程,所以SynchronizationContext为null,因此该解决方案无法工作。

我已经读过乔希·史密斯的“文章”和卡尔·希夫莱特的“材料”了。太棒了,顺便说一句。

因此,问题是:

-Is我的方法对吗?我愿意接受新的想法。

-How可以将ListBox或其他控件绑定到另一个ViewModel中的ViewModel中的属性吗?

-How我可以将OnPropertyChanged分配给UI线程,而无需单击窗口就可以应用更新吗?

--编辑

我的主要问题是显示数据。

如果我的MainViewModel看起来像这样:

代码语言:javascript
复制
public class MainViewModel
{

    private ContainerViewModel _currentContainer = new ContainerViewModel();

    public ContainerViewModel CurrentContainer
    { get { return _currentContainer; } }

    // more code...
}

然后,在视图中,要显示ProductList,我的xaml是:

代码语言:javascript
复制
<Window.DataContext>
    <ViewModels:MainViewModel />
</Window.DataContext>

<ListBox Grid.Column="0" Margin="5"
            ItemsSource="{Binding CurrentContainer.ProductList}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <DockPanel LastChildFill="True">
                <TextBlock Text="{Binding UPC}" />
                <TextBlock Text="{Binding ItemsCount}" />
            </DockPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
  • 注意:数据模板将是不同的,但是,我希望看到列表框中的项目。

当我运行应用程序时,在后台,ViewModels将被填充。如果设置了断点,则可以在可观察的列表中看到项目。

但是屏幕上没有东西,ListBox仍然是空的。

耽误您时间,实在对不起。

致以问候。

EN

回答 2

Stack Overflow用户

发布于 2015-10-24 07:26:48

可以将ProductSerialCodes定义为ObservableCollection来绑定视图。

代码语言:javascript
复制
public ObservableCollection<string> ProductSerialCodes
    { get { return _productSerialCodes; } }

另外,要更新ObservableCollection (因为它是在后台线程而不是主线程中更新的),您应该使用Dispatcher对象。

代码语言:javascript
复制
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
            {
              <<Your code>>
            }));
票数 0
EN

Stack Overflow用户

发布于 2015-10-24 13:47:02

-Is我的方法对吗?我愿意接受新的想法。

如果ProductList在运行时没有被修改,我认为最好将它声明为List,并将ProductSerialCodes声明为ObservableCollection。

-How可以将ListBox或其他控件绑定到另一个ViewModel中的ViewModel中的属性吗?

通常,父-子(子集合)类型的ViewModels与任何ItemsControl派生控件(如ListBox )都是完美的。您只需将ItemSource绑定到子项目,并为项目提供一个模板。子ViewModel将被限制在项的视图中。

-How我可以将OnPropertyChanged分配给UI线程,而无需单击窗口就可以应用更新吗?

我同意user1672994的意见,调度员可以做到。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33315555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档