【问题标题】:Instanciate UIElement from XAML从 XAML 实例化 UI 元素
【发布时间】:2018-11-06 18:11:28
【问题描述】:

我想要实现的目标听起来不像火箭科学。我要创建的是一个自定义控件,我可以直接从 XAML 向其中传递 UIElements 项目列表,因此每个元素可以不同并嵌入不同的对象(网格/文本框/面板等...)。

这是我想使用的 xaml 代码:

    <wpf:TileListDoubleItem>
        <wpf:TileListDoubleItem.FrontItem>
            <Grid>
                <TextBlock FontFamily="Calibri,Verdana" FontSize="16" FontWeight="Bold" Foreground="White" Text="Hello"></TextBlock>
            </Grid>
        </wpf:TileListDoubleItem.FrontItem>
        <wpf:TileListDoubleItem.BackItem>
            <Grid>
                <TextBlock FontFamily="Calibri,Verdana" FontSize="16" FontWeight="Bold" Foreground="White" Text="World"></TextBlock>
            </Grid>                                 
        </wpf:TileListDoubleItem.BackItem>
    </wpf:TileListDoubleItem>

这是我的自定义控制代码:

    public partial class TileListDoubleItem : UserControl, INotifyPropertyChanged
    {
        private bool _flipped;
        internal bool CanFlip { get { return true; } }

        private bool flipped
        {
            get {
                return this._flipped;
            }
            set {
                this._flipped = value;
                DisplayItem = this._flipped ? BackItem : FrontItem;
            }
        }

        public ObservableCollection<TileSide> Sides { get; set; }
        public ICommand FlipCommand;

        public TileListDoubleItem()
        {
            InitializeComponent();
            FlipCommand = new FlipCommand(this);
            flipped = false;
        }

        private UIElement displayItem { get; set; }
        public UIElement DisplayItem
        {
            get { return this.displayItem; }
            set {
                if (this.displayItem != value)
                {
                    this.displayItem = value;
                    OnPropertyChanged("DisplayItem");
                }
            }
        }

        public void Flip()
        {
            try
            {
                flipped = !flipped;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public UIElement FrontItem
        {
            get { return (UIElement)GetValue(FrontItemProperty); }
            set { SetValue(FrontItemProperty, value); }
        }

        public static readonly DependencyProperty FrontItemProperty =
        DependencyProperty.Register("FrontItem", typeof(UIElement), typeof(TileListDoubleItem), new UIPropertyMetadata(null));


        public UIElement BackItem
        {
            get { return (UIElement)GetValue(BackItemProperty); }
            set { SetValue(BackItemProperty, value); }
        }

        public static readonly DependencyProperty BackItemProperty =
        DependencyProperty.Register("BackItem", typeof(UIElement), typeof(TileListDoubleItem), new UIPropertyMetadata(null));

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

当我运行它时,我的 FrontItem 和 BackItem 都等于 null 并且永远不会设置为 UIElement(本例中为 Grid)。 我想我缺少的东西对某些人来说一定很明显。

在这里提前感谢任何人的帮助。

【问题讨论】:

  • 当您说属性值为空时,您是否在控件的构造函数中检查了这一点?在调用构造函数后,这两个属性都设置了它们的值。除此之外,尚不清楚控件应该对它们做什么。它们都没有,也没有 DisplayItem 似乎被用作您的 UserControl 的内容。您为 DisplayItem 实现 INotifyPropertyChanged 也很奇怪。它应该是另一个依赖属性。

标签: c# wpf xaml custom-controls


【解决方案1】:

您的属性已按预期设置。例如,您可以通过创建两个绑定到控件属性的TextBlocks 来确认这一点:

<wpf:TileListDoubleItem x:Name="control">
    <wpf:TileListDoubleItem.FrontItem>
        <Grid>
            <TextBlock FontFamily="Calibri,Verdana" FontSize="16" FontWeight="Bold" Foreground="White" Text="Hello"></TextBlock>
        </Grid>
    </wpf:TileListDoubleItem.FrontItem>
    <wpf:TileListDoubleItem.BackItem>
        <Grid>
            <TextBlock FontFamily="Calibri,Verdana" FontSize="16" FontWeight="Bold" Foreground="White" Text="World"></TextBlock>
        </Grid>
    </wpf:TileListDoubleItem.BackItem>
</wpf:TileListDoubleItem>

<TextBlock Text="{Binding FrontItem.Children[0].Text, ElementName=control}" />
<TextBlock Text="{Binding BackItem.Children[0].Text, ElementName=control}" />

显然,当TileListDoubleItem 的构造函数返回时,属性不会被设置。 XAML 解析器需要先实例化对象,然后才能设置其任何属性,就像您自己创建类的实例时所做的那样。

【讨论】:

  • @Chris?你试过这个还是发生了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 2015-10-16
相关资源
最近更新 更多