C# WPF依赖项属性绑定中断并始终使用默认值

C# WPF依赖项属性绑定中断并始终使用默认值,c#,.net,wpf,xaml,prism,C#,.net,Wpf,Xaml,Prism,我有一个如下定义的依赖属性。它在Childusercontrol的xaml.cs中定义。它总是使用RGB(255,0,0)的默认值,即红色 public Color ForeColor { get {return (Color)this.GetValue(ForeColorProperty); } set {this.SetValue(ForeColorProperty, value);} } public static readonly DependencyProperty

我有一个如下定义的依赖属性。它在Childusercontrol的xaml.cs中定义。它总是使用RGB(255,0,0)的默认值,即红色

public Color ForeColor
{
    get {return (Color)this.GetValue(ForeColorProperty); }
    set {this.SetValue(ForeColorProperty, value);}
}

public static readonly DependencyProperty ForeColorProperty = DependencyProperty.Register("ForeColor", typeof(Color), typeof(Childusercontrol), new PropertyMetadata(Color.FromRgb(255,0,0), OnCurrentForeColorPropertyChanged));

private static void OnCurrentForeColorPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{    
    Childusecontrol control = source as Childusecontrol;
    Color fcolor= (Color)e.NewValue;
}
该值通过xaml从父用户控件传递为

<UC:Childusercontrol ForeColor="{Binding ChildForeColor}"/>
在parentusercontrol的构造函数中,ChildForeColor属性设置如下

作为构造函数参数传递的值是蓝色的

public Color ForeColor
{
    get {return (Color)this.GetValue(ForeColorProperty); }
    set {this.SetValue(ForeColorProperty, value);}
}

public static readonly DependencyProperty ForeColorProperty = DependencyProperty.Register("ForeColor", typeof(Color), typeof(Childusercontrol), new PropertyMetadata(Color.FromRgb(255,0,0), OnCurrentForeColorPropertyChanged));

private static void OnCurrentForeColorPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{    
    Childusecontrol control = source as Childusecontrol;
    Color fcolor= (Color)e.NewValue;
}
但是,
InitializeComponent()清除dependency属性的值,因此只使用默认值

是否必须更改依赖项属性的定义?如何修复此错误?

可能的解决方案:

  • 确保父对象的childForeColor具有指定的颜色,尤其是在使用普通属性时

  • 如果在父控件中使用普通属性,请确保在初始化后更改颜色时调用INotifyPropertyChange(我猜您已经订阅了)

  • 也许改用FrameworkPropertyMetadata,然后添加flag AffectsRender-不要认为这是问题所在,但值得一试

  • 玩转绑定模式——尽管我也不认为这是真正的问题

  • 如果您使用的是2个控件,其中1个属性最有可能继承自另一个控件,请使用继承的属性,而不是-

  • 一句话,我怀疑父母的“ChildForeColor”可能是造成问题的原因,因为我乍一看,上述情况似乎没有问题

    编辑 尝试执行以下操作。在xaml中,为父控件指定一个名称x:name=“parent”,然后在绑定模式下执行此操作

    <UC:Childusercontrol ForeColor="{Binding ChildForeColor, ElementName="Parent"}"/>
    
    ChildForeColor显示正确,如果覆盖OnInitialized()并在base.OnInitialized(e)之后计算ChildForeColor的值;已运行的前景色是否仍保持不变

    我还假设您没有删除InitializeComponent()并初始化Component();在ChildForeColor=..之后出现。。。。!在构造函数中,没有显示InitializeComponent()的位置,我认为这只是为了便于阅读

    如果ForeColor在此时保持不变,并假设base.OnInitialized是在OnInitialized中运行的第一个方法。那么初始化不是问题,那么另一个建议是将ChildForeColor更改为适当的依赖属性:

    public Color ChildForeColor
        {
            get { return (Color)GetValue(ChildForeColorProperty); }
            set { SetValue(ChildForeColorProperty, value); }
        }
    
        //Register Dependency ChildForeColor Property
        public static readonly DependencyProperty ChildForeColorProperty = DependencyProperty.Register("ChildForeColor", typeof(Color), typeof(ParentControl), new FrameworkPropertyMetadata());
    

    看看这是否会改变它。

    这对我来说非常好

  • 儿童控制

    我在Xaml中为UserControl指定了一个名称,即

    <UserControl ... (all normal namespaces)... x:Name="Child">
        <Border>
           <Border.Background>
                <SolidColorBrush Color="{Binding ForeColor, ElementName=child}"/>
            </Border.Background>
        </Border>
    </UserControl>
    
    我为_ChildForeColor指定了一个值,只是为了测试,但这不是必需的。但是请注意,如果运行NotifyPropertyChanged事件,则在InitializeComponent()之前不能发生此情况;我想这是因为还没有初始化任何内容来侦听更改。因此,您有两种选择。删除OnPropertyChanged并在InitializeComponent之前指定颜色,或使用OnPropertyChanged但仅在InitializeComponent之后指定颜色。第一个解决方案仍然有效,因为属性值在组件查找该值之前已更改

  • 用于构造控件的窗口

    这有点棘手,因为您已经分配了一个接受变量的构造函数。因此,我的代码如下所示:

    public Control ParContent
    {
        get { return (ContentControl)GetValue(ParContentProperty); }
        set { SetValue(ParContentProperty, value); }
    }
    
    //Register Dependency ParContent Property
    public static readonly DependencyProperty ParContentProperty = DependencyProperty.Register("ParContent", typeof(ContentControl), typeof(MainWindow), new PropertyMetadata( ));
    
    public MainWindow()
    {
       InitializeComponent();  
       ParContent = new ParentUserControl(System.Drawing.Color.Blue);
    }
    
    在Xaml中

    <Window ...Title="MainWindow" Height="478.784" Width="736.87" x:Name="win">
        <Grid>
            <local:ChildUserControl HorizontalAlignment="Left" Height="100" Margin="122,298,0,0" VerticalAlignment="Top" Width="100"/>
            <ContentControl x:Name="Parent" Content="{Binding ParContent,ElementName=win}" HorizontalAlignment="Left" Margin="106,49,0,0" VerticalAlignment="Top" Height="79" Width="93"/>
        </Grid>
    </Window>
    
    
    

  • 正如我所说的那样,我的工作非常好,所有属性都保持其值。

    您能显示更多wpf代码吗?例如,ChildForeColor的定义在哪里/如何定义?也可能是在“OnCurrentForeColorPropertyChanged”中做了什么?@DaClan它只是一个使用NotifyPropertyChanged的常规wpf属性它是一个常规依赖属性还是一个调用INotifyProperty的常规CLR属性在属性更改时发生了更改?它是如何以及何时更改的?当您在XAML中声明
    时,您是否也在设置它的
    DataContext
    ?如果是这样,则
    ForeColor
    上的绑定将不会使用父视图模型作为其绑定源。您在“ParentUserControl的ViewModel”中谈论的是
    ChildForeColor
    属性,但在ParentUserControl构造函数中,您显然是直接在控件上设置了
    ChildForeColor
    。那没有道理。或者你真的有两个这样的属性吗?我还没有尝试覆盖OnInitialized。你能给我一些博客帖子的链接,解释wpf用户控制的生命周期吗?在这里我只能找到初始化,加载和卸载,它们没有帮助。嗯。。。我不确定是否有链接或帖子对不起,也许这里的其他人可以提供帮助。
    <UserControl ... (Usual NS)... x:Name="parent">
        <Border BorderThickness="2">
            <local:ChildUserControl Margin="5" ForeColor="{Binding ChildForeColor, ElementName=parent}"/>
            <Border.BorderBrush>
                <SolidColorBrush Color="{Binding ChildForeColor, ElementName=parent}"/>
            </Border.BorderBrush>
        </Border>
    </UserControl>
    
    public ParentUserControl(System.Drawing.Color c)
    {
        InitializeComponent();
        Color c2 = Color.FromRgb(c.R, c.G, c.B);
        ChildForeColor = c2;
    
    }
    
    private Color _ChildForeColor = Color.FromRgb(0, 255, 0);
    public Color ChildForeColor
    {
        get { return _ChildForeColor; }
        set
        {
            if (value != _ChildForeColor)
            {
                _ChildForeColor = value;
                OnPropertyChanged(() => ChildForeColor);
            }
        }
    }
    
    public Control ParContent
    {
        get { return (ContentControl)GetValue(ParContentProperty); }
        set { SetValue(ParContentProperty, value); }
    }
    
    //Register Dependency ParContent Property
    public static readonly DependencyProperty ParContentProperty = DependencyProperty.Register("ParContent", typeof(ContentControl), typeof(MainWindow), new PropertyMetadata( ));
    
    public MainWindow()
    {
       InitializeComponent();  
       ParContent = new ParentUserControl(System.Drawing.Color.Blue);
    }
    
    <Window ...Title="MainWindow" Height="478.784" Width="736.87" x:Name="win">
        <Grid>
            <local:ChildUserControl HorizontalAlignment="Left" Height="100" Margin="122,298,0,0" VerticalAlignment="Top" Width="100"/>
            <ContentControl x:Name="Parent" Content="{Binding ParContent,ElementName=win}" HorizontalAlignment="Left" Margin="106,49,0,0" VerticalAlignment="Top" Height="79" Width="93"/>
        </Grid>
    </Window>