wpf触发器依赖项属性手动刷新

wpf触发器依赖项属性手动刷新,wpf,dependency-properties,Wpf,Dependency Properties,我有一个来自RichTextBox的自定义UserControl子类。此类有一个双向绑定的依赖属性Equation 当用户把一个项目放到控件上时,我改变了等式。这会将更改正确地传播到绑定的另一端,从而触发属性更改通知,但UI不会更改。如果我将绑定更改为另一个对象并返回,则会显示更新的等式 如何在不更改绑定的情况下强制刷新?现在我设置等式=null,然后返回哪个有效,但这似乎有点老套。一定有更优雅的东西 以下是控件的相关部分。我希望发生的是在我更改方程式(Equation.Components.A

我有一个来自RichTextBox的自定义UserControl子类。此类有一个双向绑定的依赖属性Equation

当用户把一个项目放到控件上时,我改变了等式。这会将更改正确地传播到绑定的另一端,从而触发属性更改通知,但UI不会更改。如果我将绑定更改为另一个对象并返回,则会显示更新的等式

如何在不更改绑定的情况下强制刷新?现在我设置等式=null,然后返回哪个有效,但这似乎有点老套。一定有更优雅的东西

以下是控件的相关部分。我希望发生的是在我更改方程式(Equation.Components.Add(txt))之后调用OnEquationChanged回调

}

下面是双向绑定另一端的属性。在上面的代码中,由于equation.Components.Add(txt)的结果调用了equation_PropertyChanged事件

编辑--------------------------

根据注释,我尝试过使用这样的调度器(请注意,这是我第一次尝试使用调度器)

但仍然没有UI更新

编辑2--------------------------

双向绑定是在XAML中完成的

<l:EquationTextBox x:Name="ui_txtVariableEquation" Grid.Row="0" Grid.Column="2" 
                             Grid.RowSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                   AllowDrop="True"
                                   Equation="{Binding SelectedVariableVM.Variable.Equation, Mode=TwoWay}">
                </l:EquationTextBox>

Variable.equation_PropertyChanged在equation类内部引发事件时被调用

我认为问题在于绑定产生的值实际上没有改变(它仍然是相同的
equation
对象)。如果DP值没有更改,则不会调用DP更改处理程序

public class Equation : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Equation()
    {
        mComponents = new ObservableCollection<EquationComponent>();

        mComponents.CollectionChanged += new NotifyCollectionChangedEventHandler(components_CollectionChanged);
    }

    public Equation(string eqn) : this()
    {
        mComponents.Add(new EquationText(eqn));
    }

    public ObservableCollection<EquationComponent> Components
    {
        get{ return mComponents; }
        set{ mComponents = value; NotifyPropertyChanged();}
    }

    public override string ToString()
    {
        string str = "";
        for(int i=0; i<mComponents.Count; i++)
            str += mComponents[i].ToString();

        return str;
    }

    private void components_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("Components");
    }

    private ObservableCollection<EquationComponent> mComponents;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Variable : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Variable(string name = "var", VariableType type = VariableType.UnknownType) :
        this(name, "", 0, type)
    {
    }
也许,在DP更改处理程序中,您应该订阅新公式的
PropertyChanged
事件,然后在基础属性更改时重新生成文档:

private static void onEquationChanged(
    DependencyObject d,
    DependencyPropertyChangedEventArgs e)
{
    var txtBox = d as EquationTextBox;
    if (txtBox == null)
        return;

    var oldEquation = e.OldValue as Equation;
    if (oldEquation != null)
        oldEquation.PropertyChanged -= txtBox.OnEquationPropertyChanged;

    var newEquation = e.NewValue as Equation;
    if (newEquation != null)
        newEquation.PropertyChanged += txtBox.OnEquationPropertyChanged;

    txtBox.RebuildDocument();
}

private void OnEquationPropertyChanged(object sender, EventArgs e)
{
    RebuildDocument();
}

private void RebuildDocument()
{
    FlowDocument doc = this.Document;

    doc.Blocks.Clear();

    var equation = this.Equation;
    if (equation != null)
        doc.Blocks.Add(new Paragraph(new Run(equation.ToString())));
}

如果在向等式添加组件后立即调用NotifyPropertyChanged,会发生什么情况?这样就不需要进行变通了?你是说在EquationTextBox拖放处理程序中?我试过了,但似乎什么都没用。它在事件处理程序中。您是否尝试在异步调度程序中包装对NotifyPropertyChanged的调用?不,我不熟悉这些。我将查找并尝试一下。请参阅我的编辑。还是不走运(假设我做得对)
<l:EquationTextBox x:Name="ui_txtVariableEquation" Grid.Row="0" Grid.Column="2" 
                             Grid.RowSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                   AllowDrop="True"
                                   Equation="{Binding SelectedVariableVM.Variable.Equation, Mode=TwoWay}">
                </l:EquationTextBox>
public class Equation : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Equation()
    {
        mComponents = new ObservableCollection<EquationComponent>();

        mComponents.CollectionChanged += new NotifyCollectionChangedEventHandler(components_CollectionChanged);
    }

    public Equation(string eqn) : this()
    {
        mComponents.Add(new EquationText(eqn));
    }

    public ObservableCollection<EquationComponent> Components
    {
        get{ return mComponents; }
        set{ mComponents = value; NotifyPropertyChanged();}
    }

    public override string ToString()
    {
        string str = "";
        for(int i=0; i<mComponents.Count; i++)
            str += mComponents[i].ToString();

        return str;
    }

    private void components_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("Components");
    }

    private ObservableCollection<EquationComponent> mComponents;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Variable : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Variable(string name = "var", VariableType type = VariableType.UnknownType) :
        this(name, "", 0, type)
    {
    }
    public class Variable : INotifyPropertyChanged
{
    public Variable(string name, string unit, object val, VariableType type)
    {
        mEquation = new Equation(name + " = " + val.ToString() + 
        mEquation.PropertyChanged += new PropertyChangedEventHandler(equation_PropertyChanged);

    }

    ...
    public Equation Equation
    {
        get{ return mEquation; }
        set { mEquation = value; NotifyPropertyChanged(); }
    }

    private void equation_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        NotifyPropertyChanged("Equation");
    }

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }


    private Equation mEquation;
    ...
}
private static void onEquationChanged(
    DependencyObject d,
    DependencyPropertyChangedEventArgs e)
{
    var txtBox = d as EquationTextBox;
    if (txtBox == null)
        return;

    var oldEquation = e.OldValue as Equation;
    if (oldEquation != null)
        oldEquation.PropertyChanged -= txtBox.OnEquationPropertyChanged;

    var newEquation = e.NewValue as Equation;
    if (newEquation != null)
        newEquation.PropertyChanged += txtBox.OnEquationPropertyChanged;

    txtBox.RebuildDocument();
}

private void OnEquationPropertyChanged(object sender, EventArgs e)
{
    RebuildDocument();
}

private void RebuildDocument()
{
    FlowDocument doc = this.Document;

    doc.Blocks.Clear();

    var equation = this.Equation;
    if (equation != null)
        doc.Blocks.Add(new Paragraph(new Run(equation.ToString())));
}