简体   繁体   English

Silverlight是否可以使用PropertyInfo的SetValue复制UIElement?

[英]Silverlight deep copy of a UIElement using PropertyInfo's SetValue?

I have a RadComboBox from telerik which has some protected setters for a few of it's properties. 我有一个来自telerik的RadComboBox,它为其中的一些属性提供了一些受保护的设置器。 I want to be able to set each and every property so I derived from that control and I have created a custom control. 我希望能够设置每个属性,因此我从该控件派生出了一个自定义控件。 I also did the same thing for it's items component. 我也对其项目组件做了同样的事情。

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;
    }
}

In my case I have a list of RadComboBoxItems and I want to create a new list of type MyCustomComboBoxItem, so I can access the setter for each item from the first list based on the data: 在我的情况下,我有一个RadComboBoxItems列表,并且我想创建一个MyCustomComboBoxItem类型的新列表,因此我可以基于数据从第一个列表访问每个项目的设置器:

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);
        }
    }
}

I found another post with an explanation on what I am trying to do but my case is a little different and I borrowed the Load method from here: 我找到了另一篇文章,里面有关于我要做什么的解释,但是我的情况有些不同,因此我从这里借用了Load方法:

Updating ObservableCollection Item properties using INotifyPropertyChanged 使用INotifyPropertyChanged更新ObservableCollection Item属性

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);
                }
            }
        }
    }
}

Recap: What I am trying to do here is create a custom ComboBox from Telerik's RadComboBox. 回顾:我想在这里做的是从Telerik的RadComboBox创建一个自定义的ComboBox。 This has ComboBoxItems that have the IsHighlighted dependency property setter protected. 这具有受IsHighlighted依赖项属性设置器保护的ComboBoxItems。 I created MyCustomComboBoxItem to circumvent this limitation but I can't get to copy the RadComboBoxItem into MyCustomComboBoxItem. 我创建了MyCustomComboBoxItem来规避此限制,但是我无法将RadComboBoxItem复制到MyCustomComboBoxItem中。

Reason: I want to be able to set it, so I can help the user in a better experience. 原因:我希望能够进行设置,因此我可以帮助用户获得更好的体验。

Thanks. 谢谢。

The IsHightlighted Property in the RadComboBoxItem is an internal property, and probably with good reason. RadComboBoxItem中的IsHightlighted属性是一个内部属性,可能有充分的理由。 If you try to manipulate the property for your own purposes, the results will likely be unpredictable. 如果您尝试出于自己的目的操纵该属性,则结果可能是不可预测的。

At it's heart, the IsHighlighted property is simply used to trigger visual state changes. 本质上,IsHighlighted属性仅用于触发视觉状态更改。 If you just want to highlight the item under a given circumstance, the best approach is to 如果您只想在特定情况下突出显示项目,最好的方法是

  • Create a copy of the RadComboBoxItem ControlTemplate (using Blend is easiest for this). 创建RadComboBoxItem ControlTemplate的副本(为此,使用Blend最简单)。
  • Create a derived class (as you have already). 创建一个派生类(如您所愿)。
  • Add your own DependencyProperty (or property or method depending upon how you want to use it) and change the TargetType on the copied ControlTemplate and Style to match the DefaultStyleKey in your new class. 添加您自己的DependencyProperty(或属性或方法,取决于您要如何使用它),并在复制的ControlTemplate和Style上更改TargetType以与新类中的DefaultStyleKey匹配。

Now you simply need to add a new VisualStateGroup to the existing collection in the control template. 现在,您只需要向控件模板中的现有集合添加一个新的VisualStateGroup。 The VisualStates in that group should include at least one empty (default) state and your custom highlighted state. 该组中的VisualStates至少应包含一个空(默认)状态和自定义突出显示的状态。 Best practice dictates that your highlighted state should only affect properties which are not affected by other states. 最佳实践表明,突出显示的状态应仅影响不受其他状态影响的属性。

For example: 例如:

<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 >

Finally, you will just need to use the VisualStateManager to trigger the visual state change from a method in your control: 最后,您只需要使用VisualStateManager从控件中的方法触发可视状态更改:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM