【问题标题】:Silverlight deep copy of a UIElement using PropertyInfo's SetValue?使用 PropertyInfo 的 SetValue 的 UIElement 的 Silverlight 深拷贝?
【发布时间】:2011-12-27 19:50:40
【问题描述】:

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

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 类型的新列表,因此我可以根据数据从第一个列表中访问每个项目的设置器:

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。这具有受 IsHighlighted 依赖属性设置器保护的 ComboBoxItems。我创建了 MyCustomComboBoxItem 来规避这个限制,但我无法将 RadComboBoxItem 复制到 MyCustomComboBoxItem。

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

谢谢。

【问题讨论】:

  • 属性不应该是依赖属性吗?
  • 在我的项目中,受保护的属性是一个依赖属性。我只是试图简化这个例子。我想做的是创建一个基于 Telerik 的 RadComboBox 的自定义 ComboBox,其 IsHighlighted 属性是具有受保护设置器的属性。我需要有可用的高亮机制,因为我不想为用户选择一个项目,但我想让他更接近最终选择。

标签: c# silverlight silverlight-4.0 telerik uielement


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 2014-01-06
    • 2016-04-30
    相关资源
    最近更新 更多