使用MVVM在WPF中进行动态列和分组

时间:2014-05-28 08:28:03

标签: c# wpf mvvm datagrid

也许你可以帮我解决我的问题:虽然我找到了动态列或分组的各种方法,链接和方法,但我找不到将它们组合起来的方法。 我将进一步解释我的项目目标: 我想显示关于像DataGrid的体育比赛之类的信息。想象一个事件,多个玩家玩不同的运动并最终得到结果,所以我的数据网格标题看起来像:

体育|球员| TeeNumber |游戏X |游戏Y |游戏Z | ......

我的数据源为我提供了一个结果列表{Sport,Player,TeeNumber,GameNumber,Result},我从中生成一个PlayerResults列表{Sport,Player,TeeNumber {GameNumber,Result}}

现在我想显示一个可配置的游戏结果数量,我也已经通过DataTable完成了这一点,我在其中添加了Code-Behind中的列。 我如何通过Sport实现分组,最好是Expander-like,现在?

PS:游戏数量不同于不同的运动,并且对于给定的Sport,Player和GameNumber组合,只有一个或没有结果

编辑:现在有了一些摆弄和简单的想法,DataTable的默认视图是List类型,这足以使CollectionView可用,我完成了我的基本项目构想。

好的,我的模型给了我一个清单:

public class GameValue
{
    public string Sport;
    public string Player;
    public string TeeNumber;
    public string GameNumber;
    public string GameResult;
    public DateTime GameDate;
}

我在我的ViewModel中转换为不同的ObservableCollections,即基于这些类的Games和PlayerResults,它继承了实现INotifyPropertyChanged的ObservableObject类:

public class Game : ObservableObject
    {
    private string mGameNumber;
    private DateTime mGameDate;

    public string GameNumber
    {
        get { return mGameNumber; }
        set
        {
            mGameNumber = value;
            RaisePropertyChangedEvent("GameNumber");
        }
    }

    public DateTime GameDate
    {
        get { return mGameDate; }
        set
        {
            mGameDate = value;
            RaisePropertyChangedEvent("GameDate");
        }
    }
}

和我的PlayerResult类:

public class PlayerResult: Player
{
    private ObservableCollection<GameResult> mGameResults;

    public ObservableCollection<GameResult> GameResults
    {
        get { return mGameResults; }
        set
        {
            mGameResults = value;
            RaisePropertyChangedEvent("GameResults");
        }
    }

    public PlayerResult (List<GameResult> pGameResults, Player pPlayer )
    {
        Name = pPlayer.Name;
        TeeNumber = pPlayer.TeeNumber;
        Sport = pPlayer.Sport;
        GameResults = new ObservableCollection<GameResult>(pGameResults);

    }


    public String ContainsResultForGame(string mGameNumber)
    {

        var tmpResults = GameResults.Where(p => p.GameNumber == mGameNumber);
        if (tmpResults.FirstOrDefault() == null)
            return "";
        return tmpResults.First().GameNumber;
    }
}

在我的ViewModel构造函数中,我首先获取模型数据并进行转换。之后,我填写了我的DataTable 视图模型

public  MainViewModel()
{
    FetchModelData();
    FillDataTable();
}

private void FillDataTable()
{
    PlayerTable.Clear();

    PlayerTable.Columns.Add("Sport");
    PlayerTable.Columns.Add("Player");
    PlayerTable.Columns.Add("TeeNumber");

    for (int i = 1; i <= GamesShown; i++)
    {
        PlayerTable.Columns.Add(Games.ElementAt(i - 1).GameNumber);
    }

    foreach (var pResult in PlayerResults)
    {
        var tmpResult = pResult;
        var tmpRow = new string[3 + GamesShown];
        tmpRow[0] = tmpResult.Sport;
        tmpRow[1] = tmpResult.Name;
        tmpRow[2] = tmpResult.TeeNumber;
        for (int i = 0; i < GamesShown; i++)
        {
            tmpRow[3 + i] = tmpResult.ContainsResultForGame(Games[i].GameNumber);

        }
        PlayerTable.Rows.Add(tmpRow);

    }
}

GamesShown是一个简单的int值,表示我想要显示多少个游戏,在这种情况下为5作为起点。

My View从Codebehind获取DataContext:

public MainWindow()
{
        InitializeComponent();
        DataContext = new MainViewModel();
} 

这是我的XAML:

<Window x:Class="WFP_Sandbox.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" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Window.Resources>
            <CollectionViewSource x:Key="cvsPlayerResults" Source="{Binding PlayerTable}" >
                <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="Sport"/>
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>
        </Window.Resources>

        <Grid>
            <DataGrid x:Name="TableauGrid" AutoGenerateColumns="True"  CanUserReorderColumns="False" CanUserAddRows="false" ItemsSource="{Binding Source={StaticResource cvsPlayerResults}}">
                <DataGrid.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.ContainerStyle>
                            <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander IsExpanded="True" >
                                            <Expander.Header>
                                                <TextBlock  Text="{Binding Path=Sport}"/>
                                            </Expander.Header>
                                            <Expander.Content>
                                                <ItemsPresenter />
                                            </Expander.Content>
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                            </Style>
                        </GroupStyle.ContainerStyle>
                    </GroupStyle>
                </DataGrid.GroupStyle>
            </DataGrid>
        </Grid>
</Window>

新问题:如果启用扩展器,如何更改Groupstyle,以便“扩展器”旁边显示“Sport”?

对于一个示例,我可以告诉您链接到我的谷歌代码项目(希望能够从不同的计算机上工作)

0 个答案:

没有答案