1

所有,我有一个DataGridView覆盖DataGidView'OnItemsSourceChanged事件的自定义控件。在此事件中,我需要获取对相关 ViewModel 中数据集的引用。代码是

public class ResourceDataGrid : DataGrid
{
    protected override void OnItemsSourceChanged(
        System.Collections.IEnumerable oldValue, 
        System.Collections.IEnumerable newValue)
    {
        if (Equals(newValue, oldValue)) 
            return;
        base.OnItemsSourceChanged(oldValue, newValue);

        ResourceCore.ResourceManager manager = ResourceCore.ResourceManager.Instance();
        ResourceDataViewModel resourceDataViewModel = ?? // How do I get my ResourceDataViewModel
        List<string> l = manger.GetDataFor(resourceDataViewModel); 
        ...
    }
}

在标记线上,我想知道如何获得对ResourceDataViewModel resourceDataViewModel. 原因是我有多个选项卡,每个选项卡都包含一个数据网格和关联的 ViewModel,ViewModel 包含一些我需要[通过ResourceManager]检索的数据(或者还有其他更好的方法吗?)。

问题是,从上述事件中,我怎样才能得到关联ResourceDataViewModel

谢谢你的时间。

4

3 回答 3

3

获取DataContext并将其转换为视图模型类型:

var viewModel = this.DataContext as ResourceDataViewModel
于 2013-07-22T20:57:22.857 回答
1

在您的应用程序上放置对它的静态引用,当创建 VM 时,将其引用放在静态上并根据需要访问它。

于 2013-07-22T20:42:29.157 回答
1

You ask if there is a better way... In my experience if you find yourself subclassing a UI element in WPF there ususally is.

You can get away from embedding business logic (the choice of which data to display in the grid), by databinding your entire tab control to a view model.

To demonstrate - here is a very simple example. This is my XAML for the window hosting the tab control:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}">
            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="Header" Value="{Binding TabName}"></Setter>
                </Style>
            </TabControl.ItemContainerStyle>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <DataGrid ItemsSource="{Binding TabData}"></DataGrid>
                    </Grid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

The data context of my window is a TabsViewModel (I am using the NotificationObject that can be found in the PRISM NuGet Package):

public class TabsViewModel: NotificationObject
{
    public TabsViewModel()
    {
        Tabs = new[]
            {
                new TabViewModel("TAB1", "Data 1 Tab 1", "Data 2 Tab1"), 
                new TabViewModel("TAB2", "Data 1 Tab 2", "Data 2 Tab2"), 
            };
    }

    private TabViewModel _selectedTab;
    public TabViewModel SelectedTab
    {
        get { return _selectedTab; }
        set
        {
            if (Equals(value, _selectedTab)) return;
            _selectedTab = value;
            RaisePropertyChanged(() => SelectedTab);
        }
    }

    public IEnumerable<TabViewModel> Tabs { get; set; } 
}

public class TabViewModel
{
    public TabViewModel(string tabName, params string[] data)
    {
        TabName = tabName;
        TabData = data.Select(d => new RowData(){Property1 = d}).ToArray();
    }
    public string TabName { get; set; }
    public RowData[] TabData { get; set; }
}

public class RowData
{
    public string Property1 { get; set; }
}

This is obviously an over simplified case, but it means that if there is any business logic about precisely what data to show in each tab, this can reside in one of the view models, as opposed to the code behind. This gives you all the 'separation of concerns' benefits that MVVM is designed to encourage...

于 2013-07-23T17:00:04.060 回答