【问题标题】:Binding - controls are not updating绑定 - 控件不更新
【发布时间】:2018-04-16 14:38:58
【问题描述】:

我已将控件绑定到“描述”进度的类类型的某些属性。

一切似乎都很好:

  • NotifyPropertyChanged 似乎有效:它会在属性更改时引发(在更新 ProgressViewModel 类实例的属性的情况下)
  • 查看 xaml 代码时,当代码运行时,在绑定属性下会显示正确的值(例如:进度等于 0.1)。

问题是视觉上没有任何变化。所以:控件没有更新。全部。

XAML:

    <DockPanel LastChildFill="False">
        <DockPanel LastChildFill="False">
            <StackPanel x:Name="ProgressPart"
                        DockPanel.Dock="Top"
                        Visibility="{Binding Visible, Converter={StaticResource ValueConverterBoolToVisibility}}">
                <ProgressBar  Value="{Binding Path=Progress, Mode=OneWay, Converter={StaticResource ValueConverterTest}}" />
                <StackPanel Orientation="Horizontal">
                    <TextBlock>
                    <Run Text="Action:" />
                    <Run Text="{Binding Path=ActionName, Mode=OneWay}" />
                    </TextBlock>
                </StackPanel>
                <TextBlock Text="{Binding Path=ActionProgress, Mode=OneWay }" />

            </StackPanel>


            <StackPanel x:Name="MasterOKPart"
                        DockPanel.Dock="Top">

            </StackPanel>
            <StackPanel x:Name="MasterNotOKPart"
                        DockPanel.Dock="Top">

            </StackPanel>
            <StackPanel x:Name="FooterPart"
                        DockPanel.Dock="Bottom">
            </StackPanel>
        </DockPanel>
    </DockPanel>
</UserControl>

后面的控制代码:

public partial class ContentAnomalies : UserControl, INotifyPropertyChanged, IViewControl
{
    private ProgressViewModel _ProgressViewModel;
    public ProgressViewModel ProgressViewModel
    {
        get
        {
            return _ProgressViewModel;
        }
        set
        {
            _ProgressViewModel = value;
            NotifyPropertyChanged();
        }
    }

    private bool _Prepared;
    public bool Prepared
    {
        get
        {
            return _Prepared;
        }
        set
        {
            if (value == false)
            {
                _Prepared = value;
                return;
            }
            if (_Prepared==false)
            {
                ProgressViewModel = new ProgressViewModel
                {
                    Visible = true,
                    Token = new CancellationTokenSource()
                };
                Thread myNewThread = new Thread(() => Auditor.AuditContentMD(Globals.ThisAddIn.Application.ActivePresentation, this, ProgressViewModel));
                myNewThread.Start();
                //ProgressViewModel.Visible = false;

            }
        }
    }

    public ContentAnomalies()
    {
        InitializeComponent();
        //ProgressViewModel = new ProgressViewModel();
        //ProgressViewModel.Visible = true;
        this.ProgressPart.DataContext = ProgressViewModel;

    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void Prepare()
    {
        throw new NotImplementedException();
    }
}

修改progressViewModel的方法:

internal static void AuditContentMD(PPT.Presentation pres, ContentAnomalies control, ProgressViewModel progressViewModel) { 列出 contentAudits = ReturnContentAudits();

    progressViewModel.Visible = true;
    progressViewModel.Progress = 0;
    progressViewModel.ActionName = "Loading presentation objects...";
    List<Anomaly> anomalies = new List<Anomaly>();
    Audit audit;

    AuditsSupport.SpacesPositions = null;
    DateTime timeStart = DateTime.Now;
    AuditsSupport.Shapes = SupportVSTO.ReturnAllShapesFromPresentation(Globals.ThisAddIn.Application.ActivePresentation, progressViewModel, 0, (double)1 / (contentAudits.Count + 1));
    TimeSpan timeShapes = DateTime.Now - timeStart;

    for (int i = 0; i < contentAudits.Count; i++)
    {
        DateTime timeStartInternal = DateTime.Now;

        if (progressViewModel.Token.IsCancellationRequested)
        {
            return;
        }
        else
        {
            audit = contentAudits[i];
            progressViewModel.ActionName = audit.Name;
            anomalies.AddRange(contentAudits[i].PerformAudit(pres, (double)(i + 1) / (contentAudits.Count + 1), (double)1 / (contentAudits.Count + 1), progressViewModel));
        }
        progressViewModel.Progress = (double)(i + 2) / (contentAudits.Count + 1);
    }
    TimeSpan timeWhole = DateTime.Now - timeStart;
    MessageBox.Show("all:" + "    " + timeWhole.TotalSeconds);

    //control.ShowProgressBar(false);
    //control.AddAuditsListControlToPanel(anomalies, pres);
}

还有 PogressViewModelClass:

public class ProgressViewModel: INotifyPropertyChanged
{
    private double _Progress;
    public double Progress
    {
        get
        {
            return _Progress;
        }
        set
        {
            _Progress = value;
            NotifyPropertyChanged();
        }
    }
    private string _ActionName;
    public string ActionName
    {
        get
        {
            return _ActionName;
        }
        set
        {
            _ActionName = value;
            NotifyPropertyChanged();
        }
    }

    private string _ActionProgress;
    public string ActionProgress
    {
        get
        {
            return _ActionProgress;
        }
        set
        {
            _ActionProgress = value;
            NotifyPropertyChanged();
        }
    }

    private bool _Visible;
    public bool Visible
    {
        get
        {
            return _Visible;
        }
        set
        {
            _Visible = true;
            NotifyPropertyChanged();
        }
    }
    private CancellationTokenSource _Token;
    public CancellationTokenSource Token
    {
        get
        {
            return _Token;
        }
        set
        {
            _Token = value;
            NotifyPropertyChanged();
        }
    }
    public ProgressViewModel()
    {

    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

}

你知道如何解决它吗?

【问题讨论】:

  • 所有控件都没有更新。
  • 你在哪里设置你的DataContext
  • 如果我没看错,您调用的方法会在不同的线程中更改您的属性,您是否尝试过调用 Dispatcher 中的更改?
  • 设置this.ProgressPart.DataContext = ProgressViewModel 时,ProgressViewModel 属性必须先初始化。如果您稍后分配一个值,DataContext 不会神奇地更新,而是保持为空。但是,您可以将 DataContext 属性绑定到 ProgressViewModel 属性。
  • Decoder94:在 ContentAnomalies 构造函数中

标签: c# wpf data-binding


【解决方案1】:

您是否尝试将 PropertyName 添加到 NotifyPropertyChanged? 比如'NotifyPropertyChanged("ActionName")'

它在你的绑定中,应该是这样的:

TextBlock Text="{Binding ActionProgress, UpdateSourceTrigger=PropertyChanged}"

不需要将 Mode=OneWay 作为默认设置

【讨论】:

  • 我稍后再试试。
  • 如果它有效,请将我的答案标记为正确,我已经收到了很多帮助,并且想投票给那些帮助过我的人,谢谢:)
  • 设置 UpdateSourceTrigger=PropertyChanged 仅对 TwoWay 或 OneWayToSource 绑定有意义。在这里毫无意义。经常被误解,其实和INotifyPropertyChanged接口的PropertyChanged事件无关。
  • 在 NotifyPropertyChanged 调用中传递属性名称是多余的,因为方法参数设置了 CallerMemberName 属性。
  • @Clemens 对于对整个事情不熟悉的人来说,可能有很多信息可以开始。因为你写的内容很丰富,我只是感谢你,但你最后的评论毫无用处,对吧?
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 2021-11-22
  • 2023-03-26
相关资源
最近更新 更多