通过ViewModel将DataGrid绑定到模型集合

时间:2016-01-26 14:56:06

标签: c# wpf mvvm datagrid caliburn.micro

我是Caliburn.Micro的新手,但已经完成了一些基本的WPF MVVM编程,因此了解这些概念。我倾向于以模型第一种风格开发,因此将WPF DataGrid绑定到Model中定义和更新的集合时遇到问题。我应该如何最好地通过CollectionViewModel公开对View的引用,以便Model中的所有更新都通过ViewModel参考传播,而不是必须在ViewModel

Model

public class Market : PropertyChangedBase
{
    private string _MarketGroup;
    public string MarketGroup
    {
        get
        {
            return _MarketGroup;
        }
        set
        {
            if (_MarketGroup != value)
            {
                _MarketGroup = value;
                NotifyOfPropertyChange(() => MarketGroup);
            }
        }
    }

    private string _Expiry;
    public string Expiry
    {
        get
        {
            return _Expiry;
        }
        set
        {
            if (_Expiry != value)
            {
                _Expiry = value;
                NotifyOfPropertyChange(() => Expiry);
            }
        }
    }

    private string _MarketStatus;
    public string MarketStatus
    {
        get
        {
            return _MarketStatus;
        }
        set
        {
            if (_MarketStatus != value)
            {
                _MarketStatus = value;
                NotifyOfPropertyChange(() => MarketStatus);
            }
        }
    }

    private string _Epic;
    public string Epic
    {
        get
        {
            return _Epic;
        }
        set
        {
            if (_Epic != value)
            {
                _Epic = value;
                NotifyOfPropertyChange(() => Epic);
            }
        }
    }

    private string _InstrumentName;
    public string InstrumentName
    {
        get
        {
            return _InstrumentName;
        }
        set
        {
            if (_InstrumentName != value)
            {
                _InstrumentName = value;
                NotifyOfPropertyChange(() => InstrumentName);
            }
        }
    }
}

public interface IMarketService : InotifyPropertyChanged
{
    BindableCollection<Market> Markets {get;}
    void RefreshMarkets();
}

public class MarketService : PropertyChangedBase, IMarketService
{
    public MarketService()
    {
        Markets = new BindableCollection<IGMarket>();
    }

    private BindableCollection<Market> _Markets;
    public BindableCollection<Market> Markets
    {
        get
        {
            return _Markets;
        }
        private set
        {
            if (_Markets!= value)
            {
                _Markets = value;
                NotifyOfPropertyChange(() => Markets);
            }
        }
    }

    public void RefreshMarkets()
    {
        Markets.Clear();

        var markets = GetMarkets();

        foreach (var market in markets)
        {
            Markets.Add(market);
        }
    }
}

ViewModel

public class ShellViewModel : PropertyChangedBase
{
    private readonly IMarketService _MarketService;
    private readonly IAccountService _AccountService;

    public ShellViewModel(IMarketService marketService, IAccountService accountService)
    {
        _MarketService = marketService;
        _AccountService = accountService;

        Markets = new BindableCollection<IGMarket>(_MarketService.Markets);
    }

    public void Login()
    {
        Task.Run(() =>
        {
            if (_AccountService.Login())
            {
                LoggedIn = true;

                _MarketService.RefreshMarkets();
            }
        });
    }

    private BindableCollection<Market> _Markets;
    public BindableCollection<Market> Markets
    {
        get { return _Markets; }
        set
        {
            if (_Markets != value)
            {
                _Markets = value;
                NotifyOfPropertyChange(() => Markets);
            }
        }
    }
}
使用Simple Injector作为DI框架,

AccountServiceMarketService都在AppBootsrapper注册为单身。

View

<DataGrid AutoGenerateColumns="False" ColumnWidth="*" HorizontalAlignment="Stretch" x:Name="Markets" Margin="0,0,0,0" CanUserAddRows="False" CanUserDeleteRows="False"  VerticalAlignment="Stretch" Height="auto" Width="auto" Grid.ColumnSpan="2">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding InstrumentName}" Header="Instrument Name" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding Expiry}" Header="Expiry" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding MarketGroup}" Header="Market Group" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding InstrumentType}" Header="Instrument Type" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding MarketStatus}" Header="Market Status" IsReadOnly="True"/>
    </DataGrid.Columns>
</DataGrid>

Grid基本上没有任何内容,即使_MarketService.Markets包含项目。如果可能,我想让ViewViewModel回复Model BindableCollection的更改/更新?

感谢。

2 个答案:

答案 0 :(得分:1)

为什么使用单独的Markets集合?常见的设计是使用

public BindableCollection<Market> Markets
{
    get { return _MarketService.Markets; }
    set
    {
        if (_MarketService.Markets != value)
        {
            _MarketService.Markets = value;
            NotifyOfPropertyChange(() => Markets);
        }
    }
}

现在你有两个独立的集合,一个在ShellViewModel.Markets中,一个在ShellViewModel.MarketService.Markets中,它们不是指内存中的相同引用或以任何方式同步。

答案 1 :(得分:0)

您需要在datagrid

上绑定BindableCollection

在你的xaml ItemsSource={Binding Markets}

中试试这个