【问题标题】:Combobox binding empty using OnNavigatedTo method使用 OnNavigatedTo 方法将组合框绑定为空
【发布时间】:2017-11-10 10:43:50
【问题描述】:

我是使用 Prism WPF 的新手,并且对它的工作原理以及如何构建应用程序有基本的了解。

我在将数据绑定到视图中的控件时遇到问题,特别是使用“OnNavigatedTo”方法。

方法 1

我知道“OnNavigatedTo”方法是在构造函数之后调用的,但是当我调用存储库填充客户时,视图中的 ComboBox 是空的。

视图模型:

public class ViewAViewModel : BindableBase, INavigationAware
{
    private readonly IRegionManager _regionManager;
    private readonly IRepository _repository;

    public List<Customer> Customers { get; set; }

    public ViewAViewModel(IRepository repository, IRegionManager regionManager)
    {
        _repository = repository;
        _regionManager = regionManager;
        Customers = new List<Customer>();
    }

    private string _selectedCustomer;
    public string SelectedCustomer
    {
        get { return _selectedCustomer; }
        set { SetProperty(ref _selectedCustomer, value); }
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        Customers = _repository.GetCustomers();
    }

    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        return true;
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {

    }
}

查看:

<UserControl x:Class="ModuleA.Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <StackPanel>
            <ComboBox ItemsSource="{Binding Customers}" DisplayMemberPath="Name" SelectedValuePath="Id" SelectedValue="{Binding SelectedCustomer}"></ComboBox>
        </StackPanel>    
    </Grid>
</UserControl>

如果我通过构造函数初始化/填充“客户”,ComboBox 绑定工作正常,但是,当模块被添加到引导程序中的模块目录时,“客户”存储库方法被不必要地调用。我认为这并不理想。

方法 2

如果我在“客户”上使用“RaisePropertyChanged”,那么将数据绑定到 ComboBox 可以正常工作。

视图模型:

public class ViewAViewModel : BindableBase, INavigationAware
{
    private readonly IRegionManager _regionManager;
    private readonly IRepository _repository;
    private List<Customer> _customers;

    public List<Customer> Customers
    {
        get { return _customers; }
        set
        {
            _customers = value;
            RaisePropertyChanged();
        }
    }

    public ViewAViewModel(IRepository repository, IRegionManager regionManager)
    {
        _repository = repository;
        _regionManager = regionManager;
        _customers = new List<Customer>();
    }

    private string _selectedCustomer;
    public string SelectedCustomer
    {
        get { return _selectedCustomer; }
        set { SetProperty(ref _selectedCustomer, value); }
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        Customers = _repository.GetCustomers();
    }

    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        return true;
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {

    }
}

方法 2 是正确的方法吗?还是我错过了什么。

提前谢谢你。

【问题讨论】:

  • 第二种方法是正确的。由于Customers 属性是一个绑定源,它必须引发PropertyChanged 事件以通知绑定它应该更新其目标。这实际上是一个通用的数据绑定主题,与 Prism 或导航无关。
  • 谢谢,为错误分类道歉。这是我的第一个问题。

标签: c# wpf mvvm prism


【解决方案1】:

您的第一种方法是错误的,因为您没有调用 RaisePropertyChanged。 在构造函数中,您为 Customers 属性分配了一个新的空列表,因此组合框开始为空。

第二次,在 OnNavigatedTo 方法中,您将填充的列表分配给 Customers 属性,但 Customers 属性不调用 RaisePropertyChanged,因此视图不会知道更改。

您可以像第二种方法一样修复它,这通常是正确的方法。

另一种解决方案是仅在构造函数上填充列表,而不是在 OnNavigatedTo 上填充它,在这种情况下,Customers 属性不需要调用 RaisePropertyChanged,因为已使用更新的元素构造视图。

但这只有在您在视图中时不再更改客户属性时才有意义。

【讨论】:

  • 值得注意的是,还有第三种方法:可以使用List&lt;Customer&gt; 代替ObservableCollection&lt;Customer&gt;。它可以在构造函数中创建并稍后填充数据。视图将更新,因为它将监听 CollectionChanged 事件。
  • 感谢两位的回复。上述场景中的Customers 将是“单向”绑定源,即在视图中未更改。从应用程序性能的角度来看,通过构造函数加载Customers 数据并不理想,对吗?正如我在上面的问题中提到的,当一个模块被加载到模块目录中时,该模块内的视图模型上的构造函数被调用(加载数据等),然后当导航到该视图时,构造函数被再次调用。也许我误解了绑定的工作原理和/或 Prism。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多