Шаблон ячейки RadGridView

Мне нужно изменить CellTemplate RadGridView. Все примеры, которые я могу найти в Интернете, определяют столбцы статически в Xaml, а затем в этом теге столбца они определяют CellTemplate:

<telerik:RadGridView AutoGenerateColumns="False" ItemsSource="{Binding}" RowStyleSelector="{StaticResource styleSelector}">
    <telerik:RadGridView.Columns>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding ID}" CellTemplateSelector="{StaticResource templateSelector}" />
    </telerik:RadGridView.Columns>
</telerik:RadGridView>

Приведенный выше пример загружает CellTemplate только для столбца с заголовком «ID» и делает это для всех ячеек в этом столбце.

Мне удалось загрузить CellTemplates в коде позади, но это потребовало от меня передать экземпляр всей сетки в ViewModel, а также добавить свойство зависимости в GridView, чтобы связать столбцы сетки с GridViewColumnCollection в ViewModel.

Это очень грязный обходной путь, и я уверен, что меня уволят, если он увидит не те глаза. Мне нужно сделать что-то похожее на это:

<telerik:RadGridView.CellTemplateSelector>
    <local:MyTemplateSelector>
        <local:MyTemplateSelector.NormalTemplate>
            <DataTemplate>
                ...Some [Normal] template...
            </DataTemplate>
        </local:MyTemplateSelector.NormalTemplate
        <local:MyTemplateSelector.DropdownTemplate>
            <DataTemplate>
                ...Some [ComboBox] template...
            </DataTemplate>
        </local:MyTemplateSelector.DropdownTemplate>
    </local:MyTemplateSelector>
</telerik:RadGridView.CellTemplateSelector>

Честно говоря, я понятия не имею, почему этот RadGridView так затрудняет изменение CellTemplate, потому что это мешает вам изменить общее свойство, такое как цвет переднего плана в метке, найденной в ContentTemplate в самой ячейке. Любые идеи относительно того, что я сможет сделать?


person Johan Aspeling    schedule 11.07.2015    source источник
comment
Пожалуйста, обновите эту ветку, либо приняв ответ, либо предоставив подробную информацию в комментариях, либо отредактировав, либо даже самостоятельно ответив, почему она не отвечает на вашу проблему.   -  person Daniel Brose    schedule 18.05.2020


Ответы (1)


Итак, заранее, я не уверен в «правильном» способе сделать это, поскольку WPF кажется настолько контекстуальным, что действительно кажется тем, что лучше всего соответствует вашим конкретным потребностям.

Мой собственный подход к этому, вероятно, не самый рекомендуемый, но мне нужно было централизовать все варианты селекторов стилей и селекторов и использовать логику, написанную в коде, а не в xaml.

То, что я использовал, похоже на подход telerik.StyleRule, но намного проще, как в банкомате с кодом программной части. Вместо того, чтобы, возможно, определять в общей библиотеке ресурсов xaml или определять в каждом представлении, я использую классы в одной папке и просто вызываю их, используя пространство имен CLR и т. д. в xaml (хотя, конечно, это можно установить в коде программной части)

Он использует имя столбца и очень легко определяет условия, используя:

Expression<Func<BaseModelForAllTableObjectClasses,bool>>

Фактические ресурсы (шаблон данных и стили), которые он использует, определены в общей библиотеке ресурсов xaml, но при необходимости они могут быть довольно общими.

Это немного грубо, и я оставлю комментарии в случае интереса.

МойПроект.CellStyleSelector

/// <summary>
/// Used in CellStyleSelector and its inheriting classes.
/// 
/// Wouldnt be too hard to modify to allow declarative if highly desired.
/// 
/// NOTE - tried extending telerik.StyleRule, issues with setting condition value
/// </summary>
public class CellStyleRule
{
    /*
    object _Value;
    public object Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            this._Value = value;
        }
    }
     */

    // NOTE - if needing to widen use case, use <T>, but ONLY if needed
    Expression<Func<BaseDataModel, bool>> _Condition;
    public Expression<Func<BaseDataModel, bool>> Condition
    {
        get
        {
            return this._Condition;
        }
        set
        {
            this._Condition = value;
        }
    }


    Style _Style;
    public Style Style
    {
        get
        {
            return this._Style;
        }
        set
        {
            this._Style = value;
        }
    }



    public CellStyleRule(Expression<Func<BaseDataModel, bool>> c, string s)
    {
        var d = App.Current.FindResource(s);
        if (d != null)
            this.Style = d as Style;
        else
            throw new Exception("No such style resource as '" + s + "'");

        // Value = v;
        Condition = c;
    }



    /*
    public CellStyleRule(string c, string s)
    {
        var d = App.Current.FindResource(s);
        if (d != null)
            Style = d as Style;
        else
            throw new Exception("No such style resource as '" + s + "'");

        // TODO - test - guessing at how to do this based on telerik classes

        // Value = v;
        Telerik.Windows.Data.ExpressionTypeConverter converter = new Telerik.Windows.Data.ExpressionTypeConverter();
        Condition = (System.Linq.Expressions.Expression) converter.ConvertFromString(c);

        c.ToString();
    }
     */
}






// NOTE IMPORTANT - use of xaml defined ConditionalStyleSelectors is not a bad alternative approach, though diferent selector
//                  for each column it could all be defined in same resource dictionary
//                - problem is that issues encountered with Enums, so decided on this approach instead

/// <summary>
/// A variation of StyleSelecter not unlike telerik:ConditionalStyleSelector. 
/// 
/// However, rules are defined using a Dictionary<string,CellStyle> to distinct columns and use same 
/// selector, with rules (currently) defined not declarativly (xaml), but in inheriting classes, 
/// typically one for each entity type requiring a RadGridView and conditional styling.
/// </summary>
public abstract class CellStyleSelector : StyleSelector
{
    // public Dictionary<String, Dictionary<string, Style>> conditions { get; set; }


    // Use a Dictionary mapping X columns to individual Lists of rules to check
    Dictionary<string, List<CellStyleRule>> _Rules;
    public Dictionary<string, List<CellStyleRule>> Rules
    {
        get
        {
            if (this._Rules == null)
            {
                this._Rules = new Dictionary<string, List<CellStyleRule>>();
            }

            return this._Rules;
        }
        set { this._Rules = value; }
    }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        if (item is BaseDataModel)
        {
            GridViewCell cell = container as GridViewCell;
            var currentColumn = cell.Column as GridViewDataColumn;
            string key = currentColumn.DataMemberBinding.Path.Path;


            if (Rules.ContainsKey(key))
            {
                foreach (CellStyleRule rule in Rules[key])
                {
                    // string debug = DebugHelper.Debug(rule.Condition);

                    // REVERTED NOTE - if just Func<>
                    // if (rule.Condition((BaseDataModel)item))

                    // NOTE - if Expression<Func<>>, first compile then pass in param
                    if (rule.Condition.Compile()((BaseDataModel)item))
                    {
                        return rule.Style;
                    }
                }
            }

        }
        return null;
    }


}


/// <summary>
/// Used in CellCellTemplateRuleSelector and its inheriting classes.
/// 
/// Wouldnt be too hard to modify to allow declarative if highly desired.
/// </summary>
public class CellTemplateRule
{
    /*
    object _Value;
    public object Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            this._Value = value;
        }
    }
     */

    // NOTE - if needing to widen use case, use <T>, but ONLY if needed
    Expression<Func<BaseDataModel, bool>> _Condition;
    public Expression<Func<BaseDataModel, bool>> Condition
    {
        get
        {
            return this._Condition;
        }
        set
        {
            this._Condition = value;
        }
    }


    DataTemplate _Template;
    public DataTemplate Template
    {
        get
        {
            return this._Template;
        }
        set
        {
            this._Template = value;
        }
    }



    public CellTemplateRule(Expression<Func<BaseDataModel, bool>> c, string s)
    {
        var d = App.Current.FindResource(s);
        if (d != null)
            this.Template = d as DataTemplate;
        else
            throw new Exception("No such template resource as '" + s + "'");

        Condition = c;
    }


}

// Implementing class, used for any licence table
public class LicenceTableCellStyleSelector : CellStyleSelector
{
    public LicenceTableCellStyleSelector()
        : base()
    {
        this.Rules = new Dictionary<string, List<CellStyleRule>>()
        {
            { "LicenceStatus" , new List<CellStyleRule>()
                {
                    // Always most specific rules at top

                    // Error catcher, leave in as visual cue just in case
                    { new CellStyleRule(x => ((Licence)x).LicenceExpires < DateTime.Now && ((Licence)x).LicenceStatus != LicenceStatus.Expired, "CellStyle_Licence_ExpiryMismatch") } ,

                    { new CellStyleRule(x => ((Licence)x).LicenceStatus == LicenceStatus.Active, "CellStyle_Status_Active") } ,

                    // Same as != Active, as only those would through this far
                    { new CellStyleRule(x => x != null, "CellStyle_Status_Inactive") } ,


                }
            },

            { "LicenceType" , new List<CellStyleRule>()
                {                        
                    { new CellStyleRule(x => ((Licence)x).LicenceType == LicenceType.Full, "CellStyle_Licence_Full") } ,
                    { new CellStyleRule(x => ((Licence)x).LicenceType == LicenceType.Upgrade, "CellStyle_Licence_Upgrade") } ,

                    // Timed, uses fallthrough so no need to actually check unless wanting to distinct types of timed
                    { new CellStyleRule(x => x != null, "CellStyle_Licence_Timed") } ,
                }
            },

            { "LicenceExpired" , new List<CellStyleRule>()
                {                        
                    { new CellStyleRule(x => ((Licence)x).LicenceExpires < DateTime.Now && ((Licence)x).LicenceStatus != LicenceStatus.Expired, "CellStyle_Licence_ExpiryMismatch")  }, 
                    { new CellStyleRule(x => ((Licence)x).LicenceExpires < ((Licence)x).LicenceIssued, "CellStyle_Licence_ExpiryMismatch") } ,
                }
            },

            { "LicenceIssued" , new List<CellStyleRule>()
                {
                    { new CellStyleRule(x => ((Licence)x).LicenceExpires < ((Licence)x).LicenceIssued, "CellStyle_Licence_ExpiryMismatch") } ,
                }
            }
        };
    }
}

CellTemplateSelector

/// <summary>
/// Used in CellCellTemplateRuleSelector and its inheriting classes.
/// 
/// Wouldnt be too hard to modify to allow declarative if highly desired.
/// </summary>
public class CellTemplateRule
{
    /*
    object _Value;
    public object Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            this._Value = value;
        }
    }
     */

    // NOTE - if needing to widen use case, use <T>, but ONLY if needed
    Expression<Func<BaseDataModel, bool>> _Condition;
    public Expression<Func<BaseDataModel, bool>> Condition
    {
        get
        {
            return this._Condition;
        }
        set
        {
            this._Condition = value;
        }
    }


    DataTemplate _Template;
    public DataTemplate Template
    {
        get
        {
            return this._Template;
        }
        set
        {
            this._Template = value;
        }
    }



    public CellTemplateRule(Expression<Func<BaseDataModel, bool>> c, string s)
    {
        var d = App.Current.FindResource(s);
        if (d != null)
            this.Template = d as DataTemplate;
        else
            throw new Exception("No such template resource as '" + s + "'");

        Condition = c;
    }


}

// NOTE IMPORTANT - use of xaml defined ConditionalTemplateSelectors is not a bad alternative approach, though diferent selector
//                  for each column it could all be defined in same resource dictionary
//                - problem is that issues encountered with Enums, so decided on this approach instead

/// <summary>
/// See CellStyleSelector, this is a variant used with the CellTemplateSelector property
/// </summary>
public abstract class CellTemplateSelector : DataTemplateSelector
{
    // public Dictionary<String, Dictionary<string, Template>> conditions { get; set; }


    // Use a Dictionary mapping X columns to individual Lists of rules to check
    Dictionary<string, List<CellTemplateRule>> _Rules;
    public Dictionary<string, List<CellTemplateRule>> Rules
    {
        get
        {
            if (this._Rules == null)
            {
                this._Rules = new Dictionary<string, List<CellTemplateRule>>();
            }

            return this._Rules;
        }
        set { this._Rules = value; }
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is BaseDataModel)
        {
            GridViewCell cell = container as GridViewCell;
            var currentColumn = cell.Column as GridViewDataColumn;
            string key = currentColumn.DataMemberBinding.Path.Path;


            if (Rules.ContainsKey(key))
            {
                foreach (CellTemplateRule rule in Rules[key])
                {
                    // string debug = DebugHelper.Debug(rule.Condition);

                    // REVERTED NOTE - if just Func<>
                    // if (rule.Condition((BaseDataModel)item))

                    // NOTE - if Expression<Func<>>, first compile then pass in param
                    if (rule.Condition.Compile()((BaseDataModel)item))
                    {
                        return rule.Template;
                    }
                }
            }

        }
        return null;
    }


}


// Implementing class for a different table, though RadGridView can use both CellStyleSelector and CellTemplateSelector at same time, i just didnt need yet
public class OrderDongleWrapTableCellTemplateSelector : CellTemplateSelector
{
    public OrderDongleWrapTableCellTemplateSelector()
        : base()
    {
        this.Rules = new Dictionary<string, List<CellTemplateRule>>()
        {
            { "ReplacedDongle.DongleID" , new List<CellTemplateRule>()
                {
                    // Always most specific rules at top


                    { new CellTemplateRule(x => ((OrderDongleWrap)x).IsReplacementDongle == false  , "CellTemplate_OrderDongleWrap_NotReplacementDongler_NAField") },


                }
            },
            { "ReplacedDongleStatus" , new List<CellTemplateRule>()
                {
                    // Always most specific rules at top


                    { new CellTemplateRule(x => ((OrderDongleWrap)x).IsReplacementDongle == false  , "CellTemplate_OrderDongleWrap_NotReplacementDongler_NAField") },


                }
            },
            /*
             * // REVERTED - better to just set to UNKNOWN CUSTOMER explicitly before shown in table, rather than overwrite datatemplate
            { "Customer.CustomerName" , new List<CellTemplateRule>()
                {
                    // Always most specific rules at top


                    { new CellTemplateRule(x => ((OrderDongleWrap)x).Customer == null || ((OrderDongleWrap)x).Customer.CustomerID == 1 , "CellTemplate_OrderDongleWrap_UnknownCustomerField") },


                }
            },
            */
        };
    }
}

XAML-ресурсы

<!-- 
    The following are styles applied to cells or rows in RadGridViews based on StyleSelectors

    First is generic colours, which are inherited by semi-generic flag styles, which optionally 
    can be further inherited by table-specific styles (which can include tooltips and other properties)

    As a general rule, no colour style is applied directly, instead using semi-generic or table-specific 
    styles so as to make changes easier to manage. Which style actually matches which condition is 
    entirely the responsibility of the StyleSelector.

    https://en.wikipedia.org/wiki/Web_colors

    http://www.flounder.com/csharp_color_table.htm 

    <Style x:Key="CellStyle_"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
        <Setter Property="Foreground" Value=""/>
    </Style>
-->
<!--
    NOTE: to get cell text underlining to work, see http://www.telerik.com/forums/underline-cell-contents
-->

<Style x:Key="CellStyle_Green"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Green"/>
</Style>
<Style x:Key="CellStyle_DarkGreen"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="DarkGreen"/>
</Style>
<Style x:Key="CellStyle_ExtraDarkGreen"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="#004000"/>
</Style>
<Style x:Key="CellStyle_MediumBlue"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="MediumBlue"/>
</Style>
<Style x:Key="CellStyle_DarkBlue"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="DarkBlue"/>
</Style>
<Style x:Key="CellStyle_Purple"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Purple"/>
</Style>
<Style x:Key="CellStyle_Red"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="CellStyle_Crimson"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Crimson"/>
</Style>
<Style x:Key="CellStyle_DarkOrange"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="DarkOrange"/>
</Style>
<Style x:Key="CellStyle_Silver"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Silver"/>
</Style>
<Style x:Key="CellStyle_DarkGray"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="DarkGray"/>
</Style>
<Style x:Key="CellStyle_Gray"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Foreground" Value="Gray"/>
</Style>

<Style x:Key="CellStyle_RedBG_WhiteFG"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="Foreground" Value="White"/>
</Style>



<Style x:Key="CellStyle_Muted"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Gray}" />
<Style x:Key="CellStyle_Status_Active"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_ExtraDarkGreen}" />
<Style x:Key="CellStyle_Status_Inactive"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Gray}" />
<Style x:Key="CellStyle_Status_Warning"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Crimson}" />
<Style x:Key="CellStyle_Status_Error"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Red}" />
<Style x:Key="CellStyle_Status_ErrorBG"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_RedBG_WhiteFG}" />

<Style x:Key="CellStyle_Dongle_InactiveWithActiveLicences"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Status_Error}">
    <Setter Property="ToolTip" Value="This Dongle is not Active, but has Licences which are"/>
</Style>

<Style x:Key="CellStyle_Licence_Full"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}" />
<Style x:Key="CellStyle_Licence_Upgrade"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_DarkBlue}" />
<Style x:Key="CellStyle_Licence_Timed"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Purple}" />
<Style x:Key="CellStyle_Licence_ExpiryMismatch"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Status_ErrorBG}">
    <Setter Property="ToolTip" Value="Expiry doesnt match Status or Issued Date"/>
</Style>


<Style x:Key="CellStyle_OrderDongleWrap_NotReplacementDongler_NAField"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Gray}">
    <Setter Property="Content" Value="N/A"/>
</Style>
<Style x:Key="CellStyle_OrderDongleWrap_UnknownCustomerField"  TargetType="telerik:GridViewCell" BasedOn="{StaticResource CellStyle_Gray}">
    <Setter Property="Content" Value="N/A"/>
</Style>






<DataTemplate x:Key="CellTemplate_OrderDongleWrap_NotReplacementDongler_NAField">
    <TextBlock>N/A</TextBlock>
</DataTemplate>

реализация xaml для CellStyleSelector

<telerik:RadGridView.Resources>                               
    <gridviewstyleselectors:LicenceTableCellStyleSelector x:Key="LicenceTableCellStyleSelector" />
</telerik:RadGridView.Resources>

<telerik:RadGridView.Columns>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding DongleID}" Header="DongleID"  IsReadOnly="True" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceSerial}" Header="Serial"  IsReadOnly="True" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceStatus}" Header="Status"  IsReadOnly="True" 
                                CellStyleSelector="{StaticResource LicenceTableCellStyleSelector}"/>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding Product.ProductName}" Header="Product"  IsReadOnly="True" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceType}" Header="Licence Type" 
                                CellStyleSelector="{StaticResource LicenceTableCellStyleSelector}" IsReadOnly="True" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceIssued}" Header="Issued" 
                                CellStyleSelector="{StaticResource LicenceTableCellStyleSelector}" IsReadOnly="True" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceExpires}" Header="Expiry" 
                                CellStyleSelector="{StaticResource LicenceTableCellStyleSelector}" IsReadOnly="True" />
</telerik:RadGridView.Columns>

Пока у меня был только один случай для CellTemplateSelector, и вот он:

реализация xaml для CellTemplateSelector

<telerik:RadGridView.Columns>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding Dongle.DongleID}" Header="DongleID">
        <telerik:GridViewDataColumn.AggregateFunctions>
            <telerik:CountFunction ResultFormatString="{}Dongles: {0}" />
        </telerik:GridViewDataColumn.AggregateFunctions>
    </telerik:GridViewDataColumn>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding OrderRows.Count}" Header="Licences"  
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}"  />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding Customer.CustomerName}" Header="Customer"  
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}"  />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding IsReplacementDongle}" Header="Replacement?" 
                                IsVisible="False"
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}" />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding IsEducationalDongle}" Header="Educational?"  
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}"  />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding ReplacedDongle.DongleID}" Header="Replaced"  
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}"  />
    <telerik:GridViewDataColumn DataMemberBinding="{Binding ReplacedDongleStatus}" Header="Replacement Status"  
                                CellStyleSelector="{StaticResource OrderDongleWrapTableCellStyleSelector}"
                                CellTemplateSelector="{StaticResource OrderDongleWrapTableCellTemplateSelector}"/>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding OrderRows[0].OrderRowCosts[0].CostValue }" Header="Sub-Total (AUD)">
    </telerik:GridViewDataColumn>

</telerik:RadGridView.Columns>

Итак, это мой собственный подход, но он централизует условную логику и стили только в 1 классе cs для каждого целевого класса (объект GridView ItemsSource) и всего в 1 листе ресурсов для всего GridView.

Вы можете довольно легко реорганизовать декларативность, если хотите, я видел, что это возможно, но не нуждался или не хотел этого делать, поэтому я этого не делал.

Вы также можете выполнить рефакторинг, чтобы правила каскадировались из одного класса cs для всех таблиц, или даже объявлять стили на лету..? (по новому стилю и добавлению атрибутов?)

В любом случае, я надеюсь, что это поможет кому-то еще с этой проблемой

person Daniel Brose    schedule 23.07.2015
comment
Хм, это интересный подход. Мне все еще нужно динамически добавлять ячейки, и меня не столько интересует стиль ячейки, сколько содержимое. - person Johan Aspeling; 24.07.2015
comment
Они вообще не зависят от декларативных столбцов, если на самом деле этот подход был частично создан, чтобы позволить больше сосредоточиться на коде программной части, но мы по-прежнему использовали декларативные столбцы для большинства таблиц, но используем динамические столбцы для расчета затрат, поскольку у нас есть база данных валют. таблица с ProductCosts и другими таблицами, чтобы разрешить динамическое количество полей затрат и столбцов расширения. Эти селекторы работают точно так же, если вы добавите эти свойства в код программной части, а селектор CellTemplate изменяет DataTemplate на основе привязки данных. - person Daniel Brose; 27.07.2015
comment
Я предполагаю из OP, что вы настроены на создание фактических столбцов, так что это просто CellTemplateSelectors и тому подобное, которые должны быть более динамичными? Если это так, то просто добавьте свойства, которые я определяю в xaml, в коде программной части. Я также могу поделиться кодом, который я использовал для добавления своих динамических столбцов стоимости, если хотите, хотя, возможно, есть лучшие примеры этого. - person Daniel Brose; 27.07.2015