none
怎么样才能在Silverlight中显示 交叉表或者行列转置的DataGrid呢? RRS feed

  • 问题

  • 怎么样才能在Silverlight中显示 交叉表或者行列转置的DataGrid呢?

    例如

            张三   李四   ...

    语文   100    60   ...

    外语   30     70   ...

    ...

    我尝试用SQL直接将数据生成为上述的表,但是在silverlight返回的新实体集合不知道怎么才能接收,并绑定到DataGrid

     

    求思路+ 

     

    thanks

    2011年6月9日 3:21

答案

  • 0)Bellow Is A Tested Example For You.

    1) Xaml File

    <UserControl
        x:Class="SilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

        <!-- Just For Customize The Data Grid, Optional -->
        <UserControl.Resources>
            <Style
                x:Name="CssCrossHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssColumnHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssTitleCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold"></Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Left">
                </Setter>
            </Style>
            <Style
                x:Name="CssValueCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Blue">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Right">
                </Setter>
            </Style>
        </UserControl.Resources>

        <!-- Test Data Grid, Required When Testing -->
        <Grid
            x:Name="GrdRoot">
            <StackPanel
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Orientation="Vertical">
                <sdk:DataGrid
                    x:Name="DgrTest"
                    Width="600"
                    Height="300" />
                <Button
                    x:Name="CmdShow1"
                    Content="Show Test Data 1 (Name As Column Header, Course As Row Header)"></Button>
                <Button
                    x:Name="CmdShow2"
                    Content="Show Test Data 2 (Course As Column Header, Name As Row Header)"></Button>
            </StackPanel>
        </Grid>
    </UserControl>

    2)Cs File

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Collections;

    namespace SilverlightApplication1
    {


        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
                this.CmdShow1.Click += new RoutedEventHandler(CmdShow1_Click);
                this.CmdShow2.Click += new RoutedEventHandler(CmdShow2_Click);
            }

            private void CmdShow1_Click(object sender, RoutedEventArgs e)
            {
                //Name As Column Header, Course As Row Header
                var X = new T4DataCrossViewHelper()
                {
                    //Required Calling Parameters
                    DataSource = CTestData.TestData, DisplayDataGrid = this.DgrTest,
                    XTitlePropertyName = "Name", YTitlePropertyName = "Course", ValueProppertyName = "Score",
                    //Optional Calling Parameters
                    XSortType = T4DataCrossViewHelper.ESortType.Asc,
                    YSortType = T4DataCrossViewHelper.ESortType.Asc,
                    ValueFindMode = T4DataCrossViewHelper.EFindMode.Average,
                    CrossHeader = @"Course \ Name", ValueFormat = "#0.00",
                    CrossHeaderStyle = this.CssCrossHeader, ColumnHeaderStyle = this.CssColumnHeader,
                    TitleCellStyle = this.CssTitleCell, ValueCellStyle = this.CssValueCell,
                };
                X.InitDataGrid();
            }

            private void CmdShow2_Click(object sender, RoutedEventArgs e)
            {
                //Course As Column Header, Name As Row Header
                var X = new T4DataCrossViewHelper()
                {
                    //Required Calling Parameters
                    DataSource = CTestData.TestData, DisplayDataGrid = this.DgrTest,
                    XTitlePropertyName = "Course", YTitlePropertyName = "Name", ValueProppertyName = "Score",
                };
                X.InitDataGrid();
            }
        }

        //Test Data Source (I Guess Your Data From WCF Organized In This Way)
        public static class CTestData
        {
            public static List<CDataItem> TestData { get; set; }
            static CTestData()
            {
                TestData = new List<CDataItem>();
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Chinese", Score = 10.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "English", Score = 20.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Math", Score = 30.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Chinese", Score = 40.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "English", Score = 50.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Math", Score = 60.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Chinese", Score = 70.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "English", Score = 80.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Math", Score = 90.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Chinese", Score = 100.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "English", Score = 110.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 120.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 125.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Chinese", Score = 130.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "English", Score = 140.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Math", Score = 150.0 });
                TestData.Add(new CDataItem() { Name = "I", Course = "Chinese", Score = 160.0 });
                TestData.Add(new CDataItem() { Name = "I", Course = "Chinese", Score = 165.0 });
                TestData.Add(new CDataItem() { Name = "You", Course = "English", Score = 170.0 });
                TestData.Add(new CDataItem() { Name = "You", Course = "English", Score = 175.0 });
            }
        }
        public class CDataItem
        {
            public string Name { get; set; }
            public string Course { get; set; }
            public double Score { get; set; }
        }

        /// <summary>
        /// Transpose Data View Helper Class
        /// TFSoft - Still in Writting, But Maybe Cancelled Deppending On My Interest Or Your Needs.
        /// </summary>
        public class T4DataTransposeViewHelper
        {
        }

        /// <summary>
        /// Cross Data View Helper Class
        /// TFSoft - 2011/06/09
        /// TFSoft = Simple, Nice, Elegant
        /// Copyright Free, But Strongly Recommend Dont Remove TFSoft Remark.
        ///
        /// Addtional Notes:
        /// TFSoft Is An Agricultural Researcher (Really A Farmer), But Love Computer Programming.
        /// TFSoft Has Programing Expirence Of Over 30 Years, And Play With Coding 4-8 Hours A Day In Average.
        /// </summary>
        public class T4DataCrossViewHelper
        {
            /// <summary>
            /// Cross Data Source, Required
            /// </summary>
            public IEnumerable DataSource { get; set; }

            /// <summary>
            /// Display Data Grid, Required
            /// </summary>
            public DataGrid DisplayDataGrid { get; set; }

            /// <summary>
            /// Horizontal Title Property Name, Required
            /// </summary>
            public string XTitlePropertyName { get; set; }

            /// <summary>
            /// XValue Sort Type, Optional
            /// </summary>
            public ESortType XSortType { get; set; }

            /// <summary>
            /// Vertical Title Property Name, Required
            /// </summary>
            public string YTitlePropertyName { get; set; }

            /// <summary>
            /// YValue Sort Type, Optional
            /// </summary>
            public ESortType YSortType { get; set; }

            /// <summary>
            /// Value Property Name, Required
            /// </summary>
            public string ValueProppertyName { get; set; }

            /// <summary>
            /// Value Display Format, Optional
            /// </summary>
            public string ValueFormat { get; set; }

            /// <summary>
            /// Value Find Mode, Optional
            /// </summary>
            public EFindMode ValueFindMode { get; set; }

            /// <summary>
            /// Value Cell Style, Optional
            /// </summary>
            public Style ValueCellStyle { get; set; }

            /// <summary>
            /// Cross Header Content, Optional
            /// </summary>
            public object CrossHeader { get; set; }

            /// <summary>
            /// Cross Header Style, Optional
            /// </summary>
            public Style CrossHeaderStyle { get; set; }

            /// <summary>
            /// Column Header (Data Grid Column Header) Style, Optional
            /// </summary>
            public Style ColumnHeaderStyle { get; set; }

            /// <summary>
            /// Title Cell (Cell In Left Most Column) Style, Optional
            /// </summary>
            public Style TitleCellStyle { get; set; }

            /// <summary>
            /// Init Your Data Grid, Called By Your Code
            /// </summary>
            public void InitDataGrid()
            {
                DisplayDataGrid.ItemsSource = null;
                DisplayDataGrid.AutoGenerateColumns = false;
                DisplayDataGrid.Columns.Clear();

                var LnqXData = null as IEnumerable<object>;
                switch (XSortType)
                {
                case ESortType.None:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                select X1).Distinct();
                    break;
                case ESortType.Asc:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                orderby X1 ascending
                                select X1).Distinct();
                    break;
                case ESortType.Desc:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                orderby X1 descending
                                select X1).Distinct();
                    break;
                }

                var LnqYData = null as IEnumerable<object>;
                switch (YSortType)
                {
                case ESortType.None:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                select X1).Distinct();
                    break;
                case ESortType.Asc:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                orderby X1 ascending
                                select X1).Distinct();
                    break;
                case ESortType.Desc:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                orderby X1 descending
                                select X1).Distinct();
                    break;
                }

                //Title Column
                DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                {
                    Header = CrossHeader, HeaderStyle = CrossHeaderStyle,
                    Binding = new Binding() { Path = new PropertyPath(""), },
                    CellStyle = TitleCellStyle, IsReadOnly = true,
                });

                //Value Column
                foreach (var XValue in LnqXData)
                {
                    DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                    {
                        Header = XValue, HeaderStyle = ColumnHeaderStyle,
                        Binding = new Binding()
                        {
                            Path = new PropertyPath(""),
                            Converter = new CCrossDataConverter()
                            {
                                DataSource = DataSource,
                                ValueFindMode = ValueFindMode,
                                XTitlePropertyName = XTitlePropertyName,
                                YTitlePropertyName = YTitlePropertyName,
                                ValueProppertyName = ValueProppertyName,
                            },
                            ConverterParameter = XValue,
                            StringFormat = ValueFormat,
                        },
                        CellStyle = ValueCellStyle, IsReadOnly = true,
                    });
                }
                DisplayDataGrid.ItemsSource = LnqYData;
            }
            private static object InvokePropertyValue(object Instance, string PropertyName)
            {
                var Lnq = from X in Instance.GetType().GetProperties()
                          where string.Compare(X.Name, PropertyName, StringComparison.OrdinalIgnoreCase) == 0
                          select X.GetValue(Instance, null);
                var Rlt = Lnq.FirstOrDefault(); return Rlt;
            }
            /// <summary>
            /// Cross Data Value Converter, Called Only By T4CrossDataHelper
            /// </summary>
            public class CCrossDataConverter : IValueConverter
            {
                public IEnumerable DataSource { get; set; }
                public string XTitlePropertyName { get; set; }
                public string YTitlePropertyName { get; set; }
                public string ValueProppertyName { get; set; }
                public EFindMode ValueFindMode { get; set; }
                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    var Lnq = from X in DataSource.Cast<object>()
                              where InvokePropertyValue(X, XTitlePropertyName).Equals(parameter) &&
                                    InvokePropertyValue(X, YTitlePropertyName).Equals(value)
                              select InvokePropertyValue(X, ValueProppertyName);
                    var Rlt = Lnq.FirstOrDefault();
                    switch (ValueFindMode)
                    {
                    case EFindMode.First: break;
                    case EFindMode.Last: if (Rlt != null) { Rlt = Lnq.LastOrDefault(); }; break;
                    case EFindMode.Min: if (Rlt != null) { Rlt = Lnq.Min(); }; break;
                    case EFindMode.Max: if (Rlt != null) { Rlt = Lnq.Max(); }; break;
                    case EFindMode.Sum: if (Rlt != null) { Rlt = Lnq.Sum(lX => System.Convert.ToDouble(lX)); }; break;
                    case EFindMode.Average: if (Rlt != null) { Rlt = Lnq.Average(lX => System.Convert.ToDouble(lX)); }; break;
                    }
                    return Rlt;
                }
                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    return value;
                }
            }
            /// <summary>
            /// Value Find Mode Enums
            /// </summary>
            public enum EFindMode
            {
                First = 0, Last = 1, Min = 2, Max = 3, Sum = 4, Average = 5
            }
            /// <summary>
            /// Data Sort Type Enums
            /// </summary>
            public enum ESortType
            {
                None = 0, Asc = 1, Desc = 2
            }
        }
    }


    2011年6月9日 11:26
  • 前几天无法登录论坛,未能及时回答,现回答如下:

    应该指出的是,数据值 可以取平均,最大,最小,第一个,最后一个。

    1)xaml

    <UserControl
        x:Class="SilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

        <UserControl.Resources>
            <Style
                x:Name="CssYTitleHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Green">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssXTitleHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssYTitleCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Green">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Left">
                </Setter>
            </Style>
            <Style
                x:Name="CssValueCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Blue">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Right">
                </Setter>
            </Style>
        </UserControl.Resources>

        <!-- Test Data Grid, Required When Testing -->
        <Grid
            x:Name="GrdRoot">
            <StackPanel
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Orientation="Vertical">
                <sdk:DataGrid
                    x:Name="DgrTest"
                    Width="600"
                    Height="300" />
                <Button
                    x:Name="CmdShow"
                    Content="Show Corss Data"></Button>
            </StackPanel>
        </Grid>
    </UserControl>

    2)cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    namespace SilverlightApplication1
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
                this.CmdShow.Click += CmdShow_Click;
            }

            private void CmdShow_Click(object sender, RoutedEventArgs e)
            {
                var X = new T4CrossViewHelperEx()
                {
                    //Required Parameters
                    DataSource = CTestData.TestData,
                    DisplayDataGrid = this.DgrTest,
                    YTitlePropertyNames = "Name,Age",
                    XTitlePropertyName = "Course",
                    ValuePropertyName = "Score",
                    //Optional Parameters
                    YTitlePropertyCaptions = "NameEx,AgeEx",
                    ValueFormat = "#0.0",
                    ValueFindMode = T4CrossViewHelperEx.EValueFindMode.Average,
                    ValueCellStyle = this.CssValueCell,
                    YTitleCellStyle = this.CssYTitleCell,
                    YHeaderStyle = this.CssYTitleHeader,
                    XHeaderStyle = this.CssXTitleHeader,
                };
                X.InitDataGrid();
            }


            public static class CTestData
            {
                public static List<CDataItem> TestData { get; set; }
                static CTestData()
                {
                    TestData = new List<CDataItem>();
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Chinese", Score = 10.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "English", Score = 20.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Math", Score = 30.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Chinese", Score = 40.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "English", Score = 50.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Math", Score = 60.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Chinese", Score = 70.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "English", Score = 80.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Math", Score = 90.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Chinese", Score = 100.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "English", Score = 110.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 120.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 125.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Chinese", Score = 130.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "English", Score = 140.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Math", Score = 150.0 });
                    TestData.Add(new CDataItem() { Name = "I", Age = "50Y", Course = "Chinese", Score = 160.0 });
                    TestData.Add(new CDataItem() { Name = "I", Age = "50Y", Course = "Chinese", Score = 165.0 });
                    TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 170.0 });
                    TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 175.0 });
                }
            }
            public class CDataItem
            {
                public string Name { get; set; }
                public string Course { get; set; }
                public double Score { get; set; }
                public string Age { get; set; }
            }

            /// <summary>
            /// T4CrossViewHelperEx
            /// </summary>
            public class T4CrossViewHelperEx
            {
                /// <summary>
                /// DataSource, Required
                /// </summary>
                public IEnumerable DataSource { get; set; }

                /// <summary>
                /// DisplayDataGrid, Required
                /// </summary>
                public DataGrid DisplayDataGrid { get; set; }

                /// <summary>
                /// XTitlePropertyName, Required
                /// </summary>
                public string XTitlePropertyName { get; set; }

                /// <summary>
                /// YTitlePropertyNames, Required
                /// </summary>
                public string YTitlePropertyNames { get; set; }

                /// <summary>
                /// ValuePropertyName, Required
                /// </summary>
                public string ValuePropertyName { get; set; }

                /// <summary>
                /// YTitlePropertyCaptions, Optional
                /// </summary>
                public string YTitlePropertyCaptions { get; set; }

                /// <summary>
                /// XHeaderStyle, Optional
                /// </summary>
                public Style XHeaderStyle { get; set; }

                /// <summary>
                /// YHeaderStyle, Optional
                /// </summary>
                public Style YHeaderStyle { get; set; }

                /// <summary>
                /// YTitleCellStyle, Optional
                /// </summary>
                public Style YTitleCellStyle { get; set; }

                /// <summary>
                /// ValueCellStyle, Optional
                /// </summary>
                public Style ValueCellStyle { get; set; }

                /// <summary>
                /// ValueFormat, Optional
                /// </summary>
                public string ValueFormat { get; set; }

                /// <summary>
                /// ValueFindMode, Optional
                /// </summary>
                public EValueFindMode ValueFindMode { get; set; }

                /// <summary>
                /// InitDataGrid
                /// </summary>
                public void InitDataGrid()
                {

                    DisplayDataGrid.ItemsSource = null;
                    DisplayDataGrid.AutoGenerateColumns = false;
                    DisplayDataGrid.Columns.Clear();

                    var LnqYData = (from X in DataSource.Cast<object>()
                                    let X1 = GetDataItemValues(X, YTitlePropertyNames)
                                    select X1).Distinct(new CDictEQ());
                    //YTitle Columns
                    if (1 == 1)
                    {
                        var A1 = YTitlePropertyNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        var A2 = new string[] { };
                        if (!string.IsNullOrWhiteSpace(YTitlePropertyCaptions))
                        {
                            A2 = YTitlePropertyCaptions.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        }
                        var Lnq = from X in Enumerable.Range(0, A1.Length)
                                  let XPath = "[" + A1[X] + "]"
                                  let XHeader = X < A2.Length ? A2[X] : A1[X]
                                  select new { Path = XPath, Header = XHeader };
                        foreach (var Itm in Lnq)
                        {
                            DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                            {
                                IsReadOnly = true,
                                Header = Itm.Header,
                                HeaderStyle = YHeaderStyle,
                                Binding = new Binding(Itm.Path),
                                CellStyle = YTitleCellStyle,
                            });
                        };
                    }
                    //Value Column
                    if (1 == 1)
                    {
                        var LnqXData = (from X in DataSource.Cast<object>()
                                        let X1 = GetDataItemValue(X, XTitlePropertyName)
                                        orderby X1
                                        select X1).Distinct();
                        foreach (var Itm in LnqXData)
                        {
                            DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                            {
                                IsReadOnly = true,
                                Header = Itm,
                                HeaderStyle = XHeaderStyle,
                                Binding = new Binding()
                                {
                                    Path = new PropertyPath(""),
                                    StringFormat = ValueFormat,
                                    Converter = new CValueConverter()
                                    {
                                        DataSource = DataSource,
                                        XTitlePropertyName = XTitlePropertyName,
                                        ValuePropertyName = ValuePropertyName,
                                        ValueFindMode = ValueFindMode,
                                    },
                                    ConverterParameter = Itm,
                                },
                                CellStyle = ValueCellStyle,
                            });
                        }
                    }
                    DisplayDataGrid.ItemsSource = LnqYData;
                }

                /// <summary>
                /// CDictEQ, Called Only By T4CrossViewHelper
                /// </summary>
                public class CDictEQ : IEqualityComparer<Dictionary<string, object>>
                {
                    public bool Equals(Dictionary<string, object> DicA, Dictionary<string, object> DicB)
                    {
                        var Rlt = false;
                        if (DicA == null || DicB == null)
                        {
                            Rlt =
                                ((DicA == null && DicB != null) || (DicA != null && DicB == null)) ?
                                false : true;
                        }
                        else
                        {
                            var Lnq = from X in DicA.Keys
                                      where !ObjEq(DicA[X], DicB[X])
                                      select X;
                            Rlt = Lnq.Count() > 0 ? false : true;
                        }
                        return Rlt;
                    }

                    private bool ObjEq(object O1, object O2)
                    {
                        var Rlt = false;
                        if (O1 == null || O2 == null)
                        {
                            Rlt =
                                ((O1 == null && O2 != null) || (O1 != null && O2 == null)) ?
                                false : true;
                        }
                        else
                        {
                            Rlt = O1.Equals(O2) ? true : false;
                        }
                        return Rlt;
                    }

                    public int GetHashCode(Dictionary<string, object> Dic)
                    {
                        var Rlt = 0;
                        var Lnq = from X in Dic.Keys
                                  let X1 = Dic[X]
                                  let X2 = X1 == null ? 0 : X1.GetHashCode()
                                  select X2;
                        foreach (var Itm in Lnq) { Rlt = Rlt ^ Itm; }; return Rlt;
                    }
                }

                /// <summary>
                /// CValueConverter, Called Only By T4CrossViewHelper
                /// </summary>
                public class CValueConverter : IValueConverter
                {
                    public IEnumerable DataSource { get; set; }
                    public string XTitlePropertyName { get; set; }
                    public string ValuePropertyName { get; set; }
                    public EValueFindMode ValueFindMode { get; set; }
                    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                    {
                        var YValue = value as Dictionary<string, object>;
                        var XValue = parameter;
                        var Lnq = from X in DataSource.Cast<object>()
                                  let X1 = GetDataItemValues(X, string.Join(",", YValue.Keys))
                                  where (new CDictEQ()).Equals(YValue, X1)
                                  let X2 = GetDataItemValue(X, XTitlePropertyName)
                                  where (X2 == null && XValue == null) || (X2 != null && X2.Equals(XValue))
                                  let X3 = GetDataItemValue(X, ValuePropertyName)
                                  select X3;
                        var Rlt = Lnq.FirstOrDefault();
                        switch (ValueFindMode)
                        {
                        case EValueFindMode.First: break;
                        case EValueFindMode.Last: Rlt = Lnq.Last(); break;
                        case EValueFindMode.Average: if (Rlt != null) { Rlt = Lnq.Average(lX => (double)lX); }; break;
                        case EValueFindMode.Min: Rlt = Lnq.Min(); break;
                        case EValueFindMode.Max: Rlt = Lnq.Max(); break;
                        }
                        return Rlt;
                    }

                    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                    {
                        return value;
                    }
                }

                /// <summary>
                /// EValueFindMode
                /// </summary>
                public enum EValueFindMode
                {
                    First = 0, Last = 1, Average = 2, Min = 3, Max = 4
                }

                /// <summary>
                /// GetDataItemValues
                /// </summary>
                /// <param name="DataItem"></param>
                /// <param name="PropNames"></param>
                /// <returns></returns>
                private static Dictionary<string, object> GetDataItemValues(object DataItem, string PropNames)
                {
                    var Lnq = from X in PropNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                              let XKey = X
                              let XValue = GetDataItemValue(DataItem, X)
                              select new { Key = XKey, Value = XValue };
                    var Rlt = Lnq.ToDictionary(lX => lX.Key, lX => lX.Value); return Rlt;
                }

                /// <summary>
                /// GetDataItemValue
                /// </summary>
                /// <param name="DataItem"></param>
                /// <param name="PropName"></param>
                /// <returns></returns>
                private static object GetDataItemValue(object DataItem, string PropName)
                {
                    var Lnq = from X in DataItem.GetType().GetProperties()
                              where X.Name.Trim().ToUpper() == PropName.Trim().ToUpper()
                              select X.GetValue(DataItem, null);
                    var Rlt = Lnq.FirstOrDefault(); return Rlt;
                }
            }
        }
    }



    • 已标记为答案 Anton Jin 2011年6月17日 5:37
    2011年6月17日 3:35

全部回复

  • 0)只要你的SQL语句过了关,你尝试在SQL中生成交叉表也是可以的。生成后,可以直接绑定到SL的DataGrid,不过你用的是数据实体,数据实体是自动生成的,不好动态生成,因此,即使你生成了符合格式的数据,采用数据实体那套方案,要传给SL也是有一定困难的,

    1)如果你用TFSoft研制的T4Data系列,仅用5行以内代码就可实现。

    2)不过即使你不用TFSoft的T4Data,也可以把由WCF传来的数据实体,用反射的方法转置一下,生成一个新的实体,再绑定到SL的DataGrid。

    21)为什么非要用反射,是因为这些字段(数据项)未必是死的,可能需要动态转置,省得不一样的字段,重复一些没有必要的代码。

    22)反射法不是最容易的方法,而且不是一般人能搞清楚的方法。尤其是SL的反射与。net全框架的反射,相差太多,实现起来比较麻烦,T4Data早期版本,采用那反射。

     3)还一种思路,那就是动态生成DataGrid,也能实现。

    ----------------

    其实只要你愿意写代码,这个不会太难做到。

    这是一个业余老程序员对你的提示。

    如果我没事情,并且有兴趣,我会帮你写一个通用的交叉列表辅助类给你,暂时就叫 T4CrossDataViewHelper 吧,你等着。

    2011年6月9日 9:57
  • 0)Bellow Is A Tested Example For You.

    1) Xaml File

    <UserControl
        x:Class="SilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

        <!-- Just For Customize The Data Grid, Optional -->
        <UserControl.Resources>
            <Style
                x:Name="CssCrossHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssColumnHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssTitleCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold"></Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Left">
                </Setter>
            </Style>
            <Style
                x:Name="CssValueCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Blue">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Right">
                </Setter>
            </Style>
        </UserControl.Resources>

        <!-- Test Data Grid, Required When Testing -->
        <Grid
            x:Name="GrdRoot">
            <StackPanel
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Orientation="Vertical">
                <sdk:DataGrid
                    x:Name="DgrTest"
                    Width="600"
                    Height="300" />
                <Button
                    x:Name="CmdShow1"
                    Content="Show Test Data 1 (Name As Column Header, Course As Row Header)"></Button>
                <Button
                    x:Name="CmdShow2"
                    Content="Show Test Data 2 (Course As Column Header, Name As Row Header)"></Button>
            </StackPanel>
        </Grid>
    </UserControl>

    2)Cs File

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Collections;

    namespace SilverlightApplication1
    {


        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
                this.CmdShow1.Click += new RoutedEventHandler(CmdShow1_Click);
                this.CmdShow2.Click += new RoutedEventHandler(CmdShow2_Click);
            }

            private void CmdShow1_Click(object sender, RoutedEventArgs e)
            {
                //Name As Column Header, Course As Row Header
                var X = new T4DataCrossViewHelper()
                {
                    //Required Calling Parameters
                    DataSource = CTestData.TestData, DisplayDataGrid = this.DgrTest,
                    XTitlePropertyName = "Name", YTitlePropertyName = "Course", ValueProppertyName = "Score",
                    //Optional Calling Parameters
                    XSortType = T4DataCrossViewHelper.ESortType.Asc,
                    YSortType = T4DataCrossViewHelper.ESortType.Asc,
                    ValueFindMode = T4DataCrossViewHelper.EFindMode.Average,
                    CrossHeader = @"Course \ Name", ValueFormat = "#0.00",
                    CrossHeaderStyle = this.CssCrossHeader, ColumnHeaderStyle = this.CssColumnHeader,
                    TitleCellStyle = this.CssTitleCell, ValueCellStyle = this.CssValueCell,
                };
                X.InitDataGrid();
            }

            private void CmdShow2_Click(object sender, RoutedEventArgs e)
            {
                //Course As Column Header, Name As Row Header
                var X = new T4DataCrossViewHelper()
                {
                    //Required Calling Parameters
                    DataSource = CTestData.TestData, DisplayDataGrid = this.DgrTest,
                    XTitlePropertyName = "Course", YTitlePropertyName = "Name", ValueProppertyName = "Score",
                };
                X.InitDataGrid();
            }
        }

        //Test Data Source (I Guess Your Data From WCF Organized In This Way)
        public static class CTestData
        {
            public static List<CDataItem> TestData { get; set; }
            static CTestData()
            {
                TestData = new List<CDataItem>();
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Chinese", Score = 10.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "English", Score = 20.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Math", Score = 30.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Chinese", Score = 40.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "English", Score = 50.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Math", Score = 60.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Chinese", Score = 70.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "English", Score = 80.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Math", Score = 90.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Chinese", Score = 100.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "English", Score = 110.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 120.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 125.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Chinese", Score = 130.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "English", Score = 140.0 });
                TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Math", Score = 150.0 });
                TestData.Add(new CDataItem() { Name = "I", Course = "Chinese", Score = 160.0 });
                TestData.Add(new CDataItem() { Name = "I", Course = "Chinese", Score = 165.0 });
                TestData.Add(new CDataItem() { Name = "You", Course = "English", Score = 170.0 });
                TestData.Add(new CDataItem() { Name = "You", Course = "English", Score = 175.0 });
            }
        }
        public class CDataItem
        {
            public string Name { get; set; }
            public string Course { get; set; }
            public double Score { get; set; }
        }

        /// <summary>
        /// Transpose Data View Helper Class
        /// TFSoft - Still in Writting, But Maybe Cancelled Deppending On My Interest Or Your Needs.
        /// </summary>
        public class T4DataTransposeViewHelper
        {
        }

        /// <summary>
        /// Cross Data View Helper Class
        /// TFSoft - 2011/06/09
        /// TFSoft = Simple, Nice, Elegant
        /// Copyright Free, But Strongly Recommend Dont Remove TFSoft Remark.
        ///
        /// Addtional Notes:
        /// TFSoft Is An Agricultural Researcher (Really A Farmer), But Love Computer Programming.
        /// TFSoft Has Programing Expirence Of Over 30 Years, And Play With Coding 4-8 Hours A Day In Average.
        /// </summary>
        public class T4DataCrossViewHelper
        {
            /// <summary>
            /// Cross Data Source, Required
            /// </summary>
            public IEnumerable DataSource { get; set; }

            /// <summary>
            /// Display Data Grid, Required
            /// </summary>
            public DataGrid DisplayDataGrid { get; set; }

            /// <summary>
            /// Horizontal Title Property Name, Required
            /// </summary>
            public string XTitlePropertyName { get; set; }

            /// <summary>
            /// XValue Sort Type, Optional
            /// </summary>
            public ESortType XSortType { get; set; }

            /// <summary>
            /// Vertical Title Property Name, Required
            /// </summary>
            public string YTitlePropertyName { get; set; }

            /// <summary>
            /// YValue Sort Type, Optional
            /// </summary>
            public ESortType YSortType { get; set; }

            /// <summary>
            /// Value Property Name, Required
            /// </summary>
            public string ValueProppertyName { get; set; }

            /// <summary>
            /// Value Display Format, Optional
            /// </summary>
            public string ValueFormat { get; set; }

            /// <summary>
            /// Value Find Mode, Optional
            /// </summary>
            public EFindMode ValueFindMode { get; set; }

            /// <summary>
            /// Value Cell Style, Optional
            /// </summary>
            public Style ValueCellStyle { get; set; }

            /// <summary>
            /// Cross Header Content, Optional
            /// </summary>
            public object CrossHeader { get; set; }

            /// <summary>
            /// Cross Header Style, Optional
            /// </summary>
            public Style CrossHeaderStyle { get; set; }

            /// <summary>
            /// Column Header (Data Grid Column Header) Style, Optional
            /// </summary>
            public Style ColumnHeaderStyle { get; set; }

            /// <summary>
            /// Title Cell (Cell In Left Most Column) Style, Optional
            /// </summary>
            public Style TitleCellStyle { get; set; }

            /// <summary>
            /// Init Your Data Grid, Called By Your Code
            /// </summary>
            public void InitDataGrid()
            {
                DisplayDataGrid.ItemsSource = null;
                DisplayDataGrid.AutoGenerateColumns = false;
                DisplayDataGrid.Columns.Clear();

                var LnqXData = null as IEnumerable<object>;
                switch (XSortType)
                {
                case ESortType.None:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                select X1).Distinct();
                    break;
                case ESortType.Asc:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                orderby X1 ascending
                                select X1).Distinct();
                    break;
                case ESortType.Desc:
                    LnqXData = (from X in DataSource.Cast<object>()
                                let X1 = InvokePropertyValue(X, XTitlePropertyName)
                                orderby X1 descending
                                select X1).Distinct();
                    break;
                }

                var LnqYData = null as IEnumerable<object>;
                switch (YSortType)
                {
                case ESortType.None:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                select X1).Distinct();
                    break;
                case ESortType.Asc:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                orderby X1 ascending
                                select X1).Distinct();
                    break;
                case ESortType.Desc:
                    LnqYData = (from X in DataSource.Cast<Object>()
                                let X1 = InvokePropertyValue(X, YTitlePropertyName)
                                orderby X1 descending
                                select X1).Distinct();
                    break;
                }

                //Title Column
                DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                {
                    Header = CrossHeader, HeaderStyle = CrossHeaderStyle,
                    Binding = new Binding() { Path = new PropertyPath(""), },
                    CellStyle = TitleCellStyle, IsReadOnly = true,
                });

                //Value Column
                foreach (var XValue in LnqXData)
                {
                    DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                    {
                        Header = XValue, HeaderStyle = ColumnHeaderStyle,
                        Binding = new Binding()
                        {
                            Path = new PropertyPath(""),
                            Converter = new CCrossDataConverter()
                            {
                                DataSource = DataSource,
                                ValueFindMode = ValueFindMode,
                                XTitlePropertyName = XTitlePropertyName,
                                YTitlePropertyName = YTitlePropertyName,
                                ValueProppertyName = ValueProppertyName,
                            },
                            ConverterParameter = XValue,
                            StringFormat = ValueFormat,
                        },
                        CellStyle = ValueCellStyle, IsReadOnly = true,
                    });
                }
                DisplayDataGrid.ItemsSource = LnqYData;
            }
            private static object InvokePropertyValue(object Instance, string PropertyName)
            {
                var Lnq = from X in Instance.GetType().GetProperties()
                          where string.Compare(X.Name, PropertyName, StringComparison.OrdinalIgnoreCase) == 0
                          select X.GetValue(Instance, null);
                var Rlt = Lnq.FirstOrDefault(); return Rlt;
            }
            /// <summary>
            /// Cross Data Value Converter, Called Only By T4CrossDataHelper
            /// </summary>
            public class CCrossDataConverter : IValueConverter
            {
                public IEnumerable DataSource { get; set; }
                public string XTitlePropertyName { get; set; }
                public string YTitlePropertyName { get; set; }
                public string ValueProppertyName { get; set; }
                public EFindMode ValueFindMode { get; set; }
                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    var Lnq = from X in DataSource.Cast<object>()
                              where InvokePropertyValue(X, XTitlePropertyName).Equals(parameter) &&
                                    InvokePropertyValue(X, YTitlePropertyName).Equals(value)
                              select InvokePropertyValue(X, ValueProppertyName);
                    var Rlt = Lnq.FirstOrDefault();
                    switch (ValueFindMode)
                    {
                    case EFindMode.First: break;
                    case EFindMode.Last: if (Rlt != null) { Rlt = Lnq.LastOrDefault(); }; break;
                    case EFindMode.Min: if (Rlt != null) { Rlt = Lnq.Min(); }; break;
                    case EFindMode.Max: if (Rlt != null) { Rlt = Lnq.Max(); }; break;
                    case EFindMode.Sum: if (Rlt != null) { Rlt = Lnq.Sum(lX => System.Convert.ToDouble(lX)); }; break;
                    case EFindMode.Average: if (Rlt != null) { Rlt = Lnq.Average(lX => System.Convert.ToDouble(lX)); }; break;
                    }
                    return Rlt;
                }
                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    return value;
                }
            }
            /// <summary>
            /// Value Find Mode Enums
            /// </summary>
            public enum EFindMode
            {
                First = 0, Last = 1, Min = 2, Max = 3, Sum = 4, Average = 5
            }
            /// <summary>
            /// Data Sort Type Enums
            /// </summary>
            public enum ESortType
            {
                None = 0, Asc = 1, Desc = 2
            }
        }
    }


    2011年6月9日 11:26
  • 谢谢腾飞给的解答,小弟受益匪浅,完全能满足我的需要,

     

    现在我正在研究一个新的问题,

    例如

            班级     语文   外语  ...

    张三   甲     100   60 ...

    李四   乙     30    70 ...

    ...

    是否可以添加一些 其它字段来呢? 例如上面的班级,我目前也正在尝试

     


    2011年6月11日 2:09
  • 如果需要帮助,请尽量列举数据源的格式,并且附上模拟的数据

    这样,我搞起来就省去了很多时间,也更能满足你的要求。


    这里的提问者总是不给出模拟数据,让有心帮你解决的人,添加了不少繁琐的事情,

    还有我不喜欢C#,原因是很多C#程序员采用违背自然语言习惯的但又是非常流行的“驼峰命名法”进行变量命名,看起来特别别扭,因此,给出的代码和你们的有点不一样,可能让你看起来不很舒服。(我是用VB.net的,C#只是最近刚接触的语言)。

    TFSoft一贯追求简单/美好/高雅

    TFSoft = Simple, Nice, Elegant.



    -------------------------------------------------

    增加一些字段,我觉得应该不会太复杂,

    友情提示:

     

    1)YTitlePropertyName ==> YTitlePropertyNames ...

    2) 在你理解了我良苦用心的基础上,很快就能自己修改一下相应代码。

     

     




    2011年6月11日 5:13
  • TF的答案正确,我就标记啦!
    努力!完成了js解析器,还差一个svg插件,一个绘图程序,做好自己,呵呵~!
    2011年6月11日 10:01
    版主
  • 模拟数据

    修改实体

     //Test Data Source (I Guess Your Data From WCF Organized In This Way)
     public static class CTestData
     {
     public static List<CDataItem> TestData { get; set; }
     static CTestData()
     {
      TestData = new List<CDataItem>();
      TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Chinese", Score = 10.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "English", Score = 20.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Math", Score = 30.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Chinese", Score = 40.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "English", Score = 50.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Math", Score = 60.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Chinese", Score = 70.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "English", Score = 80.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Math", Score = 90.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Chinese", Score = 100.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "English", Score = 110.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 120.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 125.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Chinese", Score = 130.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "English", Score = 140.0 });
      TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Math", Score = 150.0 });
      TestData.Add(new CDataItem() { Name = "I", Age="50Y", Course = "Chinese", Score = 160.0 });
      TestData.Add(new CDataItem() { Name = "I", Age = "50Y", Course = "Chinese", Score = 165.0 });
      TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 170.0 });
      TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 175.0 });
     }
     }
     public class CDataItem
     {
     public string Name { get; set; }
     public string Course { get; set; }
     public double Score { get; set; }
     public string Age { get; set; }
     }
    
      //Title Column
      DisplayDataGrid.Columns.Add(new DataGridTextColumn()
      {
      Header = CrossHeader,
      HeaderStyle = CrossHeaderStyle,
      Binding = new Binding() { Path = new PropertyPath(""), },
      CellStyle = TitleCellStyle,
      IsReadOnly = true,
      });
    
      //新增加需要显示的Age Column
      DisplayDataGrid.Columns.Add(new DataGridTextColumn()
      {
      Header="Age",
      Binding = new Binding() { Path = new PropertyPath("Age"), },
      IsReadOnly = true,
      });
    

     

    期望结果:

                Age Chinese English Math

    TFSoft1        10        20       30
    TFSoft2        40        50       60
    TFSoft3        70        80       90
    TFSoft4        100      110     120
    TFSoft5        130      140     150
    I           50Y 160       
    You       60Y 170   

     

     



    2011年6月11日 16:53
  • 前几天无法登录论坛,未能及时回答,现回答如下:

    应该指出的是,数据值 可以取平均,最大,最小,第一个,最后一个。

    1)xaml

    <UserControl
        x:Class="SilverlightApplication1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

        <UserControl.Resources>
            <Style
                x:Name="CssYTitleHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Green">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssXTitleHeader"
                TargetType="sdk:DataGridColumnHeader">
                <Setter
                    Property="Foreground"
                    Value="Red">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Center">
                </Setter>
                <Setter
                    Property="FontWeight"
                    Value="Bold">
                </Setter>
            </Style>
            <Style
                x:Name="CssYTitleCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Green">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Left">
                </Setter>
            </Style>
            <Style
                x:Name="CssValueCell"
                TargetType="sdk:DataGridCell">
                <Setter
                    Property="Foreground"
                    Value="Blue">
                </Setter>
                <Setter
                    Property="HorizontalContentAlignment"
                    Value="Right">
                </Setter>
            </Style>
        </UserControl.Resources>

        <!-- Test Data Grid, Required When Testing -->
        <Grid
            x:Name="GrdRoot">
            <StackPanel
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Orientation="Vertical">
                <sdk:DataGrid
                    x:Name="DgrTest"
                    Width="600"
                    Height="300" />
                <Button
                    x:Name="CmdShow"
                    Content="Show Corss Data"></Button>
            </StackPanel>
        </Grid>
    </UserControl>

    2)cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    namespace SilverlightApplication1
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
                this.CmdShow.Click += CmdShow_Click;
            }

            private void CmdShow_Click(object sender, RoutedEventArgs e)
            {
                var X = new T4CrossViewHelperEx()
                {
                    //Required Parameters
                    DataSource = CTestData.TestData,
                    DisplayDataGrid = this.DgrTest,
                    YTitlePropertyNames = "Name,Age",
                    XTitlePropertyName = "Course",
                    ValuePropertyName = "Score",
                    //Optional Parameters
                    YTitlePropertyCaptions = "NameEx,AgeEx",
                    ValueFormat = "#0.0",
                    ValueFindMode = T4CrossViewHelperEx.EValueFindMode.Average,
                    ValueCellStyle = this.CssValueCell,
                    YTitleCellStyle = this.CssYTitleCell,
                    YHeaderStyle = this.CssYTitleHeader,
                    XHeaderStyle = this.CssXTitleHeader,
                };
                X.InitDataGrid();
            }


            public static class CTestData
            {
                public static List<CDataItem> TestData { get; set; }
                static CTestData()
                {
                    TestData = new List<CDataItem>();
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Chinese", Score = 10.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "English", Score = 20.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft1", Course = "Math", Score = 30.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Chinese", Score = 40.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "English", Score = 50.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft2", Course = "Math", Score = 60.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Chinese", Score = 70.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "English", Score = 80.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft3", Course = "Math", Score = 90.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Chinese", Score = 100.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "English", Score = 110.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 120.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft4", Course = "Math", Score = 125.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Chinese", Score = 130.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "English", Score = 140.0 });
                    TestData.Add(new CDataItem() { Name = "TFSoft5", Course = "Math", Score = 150.0 });
                    TestData.Add(new CDataItem() { Name = "I", Age = "50Y", Course = "Chinese", Score = 160.0 });
                    TestData.Add(new CDataItem() { Name = "I", Age = "50Y", Course = "Chinese", Score = 165.0 });
                    TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 170.0 });
                    TestData.Add(new CDataItem() { Name = "You", Age = "60Y", Course = "English", Score = 175.0 });
                }
            }
            public class CDataItem
            {
                public string Name { get; set; }
                public string Course { get; set; }
                public double Score { get; set; }
                public string Age { get; set; }
            }

            /// <summary>
            /// T4CrossViewHelperEx
            /// </summary>
            public class T4CrossViewHelperEx
            {
                /// <summary>
                /// DataSource, Required
                /// </summary>
                public IEnumerable DataSource { get; set; }

                /// <summary>
                /// DisplayDataGrid, Required
                /// </summary>
                public DataGrid DisplayDataGrid { get; set; }

                /// <summary>
                /// XTitlePropertyName, Required
                /// </summary>
                public string XTitlePropertyName { get; set; }

                /// <summary>
                /// YTitlePropertyNames, Required
                /// </summary>
                public string YTitlePropertyNames { get; set; }

                /// <summary>
                /// ValuePropertyName, Required
                /// </summary>
                public string ValuePropertyName { get; set; }

                /// <summary>
                /// YTitlePropertyCaptions, Optional
                /// </summary>
                public string YTitlePropertyCaptions { get; set; }

                /// <summary>
                /// XHeaderStyle, Optional
                /// </summary>
                public Style XHeaderStyle { get; set; }

                /// <summary>
                /// YHeaderStyle, Optional
                /// </summary>
                public Style YHeaderStyle { get; set; }

                /// <summary>
                /// YTitleCellStyle, Optional
                /// </summary>
                public Style YTitleCellStyle { get; set; }

                /// <summary>
                /// ValueCellStyle, Optional
                /// </summary>
                public Style ValueCellStyle { get; set; }

                /// <summary>
                /// ValueFormat, Optional
                /// </summary>
                public string ValueFormat { get; set; }

                /// <summary>
                /// ValueFindMode, Optional
                /// </summary>
                public EValueFindMode ValueFindMode { get; set; }

                /// <summary>
                /// InitDataGrid
                /// </summary>
                public void InitDataGrid()
                {

                    DisplayDataGrid.ItemsSource = null;
                    DisplayDataGrid.AutoGenerateColumns = false;
                    DisplayDataGrid.Columns.Clear();

                    var LnqYData = (from X in DataSource.Cast<object>()
                                    let X1 = GetDataItemValues(X, YTitlePropertyNames)
                                    select X1).Distinct(new CDictEQ());
                    //YTitle Columns
                    if (1 == 1)
                    {
                        var A1 = YTitlePropertyNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        var A2 = new string[] { };
                        if (!string.IsNullOrWhiteSpace(YTitlePropertyCaptions))
                        {
                            A2 = YTitlePropertyCaptions.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        }
                        var Lnq = from X in Enumerable.Range(0, A1.Length)
                                  let XPath = "[" + A1[X] + "]"
                                  let XHeader = X < A2.Length ? A2[X] : A1[X]
                                  select new { Path = XPath, Header = XHeader };
                        foreach (var Itm in Lnq)
                        {
                            DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                            {
                                IsReadOnly = true,
                                Header = Itm.Header,
                                HeaderStyle = YHeaderStyle,
                                Binding = new Binding(Itm.Path),
                                CellStyle = YTitleCellStyle,
                            });
                        };
                    }
                    //Value Column
                    if (1 == 1)
                    {
                        var LnqXData = (from X in DataSource.Cast<object>()
                                        let X1 = GetDataItemValue(X, XTitlePropertyName)
                                        orderby X1
                                        select X1).Distinct();
                        foreach (var Itm in LnqXData)
                        {
                            DisplayDataGrid.Columns.Add(new DataGridTextColumn()
                            {
                                IsReadOnly = true,
                                Header = Itm,
                                HeaderStyle = XHeaderStyle,
                                Binding = new Binding()
                                {
                                    Path = new PropertyPath(""),
                                    StringFormat = ValueFormat,
                                    Converter = new CValueConverter()
                                    {
                                        DataSource = DataSource,
                                        XTitlePropertyName = XTitlePropertyName,
                                        ValuePropertyName = ValuePropertyName,
                                        ValueFindMode = ValueFindMode,
                                    },
                                    ConverterParameter = Itm,
                                },
                                CellStyle = ValueCellStyle,
                            });
                        }
                    }
                    DisplayDataGrid.ItemsSource = LnqYData;
                }

                /// <summary>
                /// CDictEQ, Called Only By T4CrossViewHelper
                /// </summary>
                public class CDictEQ : IEqualityComparer<Dictionary<string, object>>
                {
                    public bool Equals(Dictionary<string, object> DicA, Dictionary<string, object> DicB)
                    {
                        var Rlt = false;
                        if (DicA == null || DicB == null)
                        {
                            Rlt =
                                ((DicA == null && DicB != null) || (DicA != null && DicB == null)) ?
                                false : true;
                        }
                        else
                        {
                            var Lnq = from X in DicA.Keys
                                      where !ObjEq(DicA[X], DicB[X])
                                      select X;
                            Rlt = Lnq.Count() > 0 ? false : true;
                        }
                        return Rlt;
                    }

                    private bool ObjEq(object O1, object O2)
                    {
                        var Rlt = false;
                        if (O1 == null || O2 == null)
                        {
                            Rlt =
                                ((O1 == null && O2 != null) || (O1 != null && O2 == null)) ?
                                false : true;
                        }
                        else
                        {
                            Rlt = O1.Equals(O2) ? true : false;
                        }
                        return Rlt;
                    }

                    public int GetHashCode(Dictionary<string, object> Dic)
                    {
                        var Rlt = 0;
                        var Lnq = from X in Dic.Keys
                                  let X1 = Dic[X]
                                  let X2 = X1 == null ? 0 : X1.GetHashCode()
                                  select X2;
                        foreach (var Itm in Lnq) { Rlt = Rlt ^ Itm; }; return Rlt;
                    }
                }

                /// <summary>
                /// CValueConverter, Called Only By T4CrossViewHelper
                /// </summary>
                public class CValueConverter : IValueConverter
                {
                    public IEnumerable DataSource { get; set; }
                    public string XTitlePropertyName { get; set; }
                    public string ValuePropertyName { get; set; }
                    public EValueFindMode ValueFindMode { get; set; }
                    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                    {
                        var YValue = value as Dictionary<string, object>;
                        var XValue = parameter;
                        var Lnq = from X in DataSource.Cast<object>()
                                  let X1 = GetDataItemValues(X, string.Join(",", YValue.Keys))
                                  where (new CDictEQ()).Equals(YValue, X1)
                                  let X2 = GetDataItemValue(X, XTitlePropertyName)
                                  where (X2 == null && XValue == null) || (X2 != null && X2.Equals(XValue))
                                  let X3 = GetDataItemValue(X, ValuePropertyName)
                                  select X3;
                        var Rlt = Lnq.FirstOrDefault();
                        switch (ValueFindMode)
                        {
                        case EValueFindMode.First: break;
                        case EValueFindMode.Last: Rlt = Lnq.Last(); break;
                        case EValueFindMode.Average: if (Rlt != null) { Rlt = Lnq.Average(lX => (double)lX); }; break;
                        case EValueFindMode.Min: Rlt = Lnq.Min(); break;
                        case EValueFindMode.Max: Rlt = Lnq.Max(); break;
                        }
                        return Rlt;
                    }

                    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                    {
                        return value;
                    }
                }

                /// <summary>
                /// EValueFindMode
                /// </summary>
                public enum EValueFindMode
                {
                    First = 0, Last = 1, Average = 2, Min = 3, Max = 4
                }

                /// <summary>
                /// GetDataItemValues
                /// </summary>
                /// <param name="DataItem"></param>
                /// <param name="PropNames"></param>
                /// <returns></returns>
                private static Dictionary<string, object> GetDataItemValues(object DataItem, string PropNames)
                {
                    var Lnq = from X in PropNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                              let XKey = X
                              let XValue = GetDataItemValue(DataItem, X)
                              select new { Key = XKey, Value = XValue };
                    var Rlt = Lnq.ToDictionary(lX => lX.Key, lX => lX.Value); return Rlt;
                }

                /// <summary>
                /// GetDataItemValue
                /// </summary>
                /// <param name="DataItem"></param>
                /// <param name="PropName"></param>
                /// <returns></returns>
                private static object GetDataItemValue(object DataItem, string PropName)
                {
                    var Lnq = from X in DataItem.GetType().GetProperties()
                              where X.Name.Trim().ToUpper() == PropName.Trim().ToUpper()
                              select X.GetValue(DataItem, null);
                    var Rlt = Lnq.FirstOrDefault(); return Rlt;
                }
            }
        }
    }



    • 已标记为答案 Anton Jin 2011年6月17日 5:37
    2011年6月17日 3:35
  • 太强了,顶起

    我什么才嫩有次造就呢,哈哈

     

    这种方式对于MVVM模式来说,是不是不好应用?

    2011年6月17日 6:02