使用PropertyInfo的SetValue的UIElement的Silverlight深层副本?

时间:2011-12-27 19:50:40

标签: c# silverlight silverlight-4.0 telerik uielement

我有一个来自telerik的RadComboBox,它有一些受保护的设置器,用于它的一些属性。我希望能够设置每个属性,所以我从该控件派生,我创建了一个自定义控件。我也为它的项目组件做了同样的事情。

public class RadComboBoxItem : ListBoxItem
{

    ...

    public bool IsHighlighted
{
    get
    {
        return (bool)GetValue(IsHighlightedProperty);
    }
    protected set
    {
        this.SetValue(IsHighlightedPropertyKey, value);
    }
}

    ...

}

public class MyCustomComboBoxItem : RadComboBoxItem 
{
    public void HighlightItem(bool _default)
    {
        this.IsHighlighted = _default;
    }
}

在我的情况下,我有一个RadComboBoxItems列表,我想创建一个MyCustomComboBoxItem类型的新列表,所以我可以根据数据访问第一个列表中每个项目的setter:

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        ...

        foreach (RadComboBoxItem _item in _listOfRadComboBoxItems)
        {
            MyCustomComboBoxItem _customCBI = new MyCustomComboBoxItem();
            _customCBI.Load(_customCBI.GetType(), _item, true);
            _listOfCustomCBI.Add(_newB2);
        }
    }
}

我发现另一篇文章解释了我要做的事情,但我的情况有点不同,我从这里借用了Load方法:

Updating ObservableCollection Item properties using INotifyPropertyChanged

public static class ExtentionMethods
{
    public static void Load<T>(this T target, Type type, T source, bool deep)
    {
        foreach (PropertyInfo property in type.GetProperties())
        {
            if (property.CanWrite && property.CanRead)
            {
                if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
                {
                    property.SetValue(target, property.GetValue(source, null), null);
                }
                else
                {
                    object targetPropertyReference = property.GetValue(target, null);
                    targetPropertyReference.Load(targetPropertyReference.GetType(), property.GetValue(source, null), deep);
                }
            }
        }
    }
}

回顾:我在这里要做的是从Telerik的RadComboBox创建一个自定义ComboBox。这有ComboBoxItems,它具有受保护的IsHighlighted依赖项属性setter。我创建了MyCustomComboBoxItem来规避这个限制,但我无法将RadComboBoxItem复制到MyCustomComboBoxItem。

原因:我希望能够设置它,因此我可以帮助用户获得更好的体验。

感谢。

1 个答案:

答案 0 :(得分:0)

RadComboBoxItem中的IsHightlighted属性是一个内部属性,可能有充分的理由。如果您尝试为自己的目的操纵该属性,结果可能是不可预测的。

在它的核心,IsHighlighted属性仅用于触发视觉状态变化。 如果您只是想在特定情况下突出显示该项目,最好的方法是

  • 创建RadComboBoxItem ControlTemplate的副本(使用Blend对此最简单)。
  • 创建派生类(就像您已经拥有的那样)。
  • 添加您自己的DependencyProperty(或属性或方法,具体取决于您希望如何使用它),并更改复制的ControlTemplate和Style上的TargetType以匹配新类中的DefaultStyleKey。

现在您只需要将新的VisualStateGroup添加到控件模板中的现有集合中。该组中的VisualStates应至少包含一个空(默认)状态和自定义突出显示状态。最佳实践要求您突出显示的状态应仅影响不受其他状态影响的属性。

例如:

<ControlTemplate TargetType="controls:MyCustomComboBox">
     <Grid x:Name="VisualRoot">
                    ...
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
                            ...
                        <VisualStateGroup x:Name="MyHighlightStates">
                            <VisualState x:Name="NotHighlightedState" />
                            <VisualState x:Name="MyHightlightedState">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyHighlightElement" Storyboard.TargetProperty="Visibility">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
        <Border x:Name="MyHighlightElement" Background="Yellow" Visibility="Collapsed"/>

    ...
    </Grid>
</ControlTemplate >

最后,您只需要使用VisualStateManager来触发控件中方法的可视状态更改:

VisualStateManager.GoToState(this, "MyHightlightedState", true);