将INotifyPropertyChanged类绑定为另一个类中的Property

时间:2012-10-09 08:10:30

标签: c# .net wpf

我有一个具有相当长的运行过程的类,我希望GUI能够取得进展。

该类有一个名为Progress的属性,它是一个实现INotifyPropertyChanged的类。我正在使用BusyWorker并将类的Progress属性绑定到它的datacontext,但只要进度发生变化,BusyWorker就不会显示任何内容。我不知道我在这里是否有任何意义,所以这里有一些代码:

有问题的课程:

public class MyClass
{
  public Progress MyProgress { get; set; }

  public void Run()
  {
    MyProgress = new Progress();
    MyProgress.Status = "Initialising";
    // Do stuff, update progress, etc.
  }
}

public class Progress : INotifyPropertyChanged
{
  private string status;

  public string Status
  {
    get { return status; }
    set
    {
      status = value;
      OnPropertyChanged("Status");
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void OnPropertyChanged(string info)
  {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(info));
  }
}

XAML:

// ...
<xctk:BusyIndicator HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="busyIndicator" VerticalAlignment="Stretch" BusyContent="{Binding}">
    <xctk:BusyIndicator.BusyContentTemplate>
        <DataTemplate>
            <StackPanel Margin="4">
                <TextBlock Text="{Binding Status}" FontWeight="Bold" HorizontalAlignment="Left"/>
            </StackPanel>
        </DataTemplate>
    </xctk:BusyIndicator.BusyContentTemplate>
</xctk:BusyIndicator>
// ...

XAML.CS:

MyClass test = new MyClass();
BusyIndicator.DataContext = test.MyProgress;
BusyIndicator.IsBusy = true;
test.Run();

如果我这样运行,并在OnPropertyChanged电话停留,PropertChanged始终为空。如果我在我的xaml.cs中创建一个单独的Progress对象,它可以正常工作,但我希望我的'Run'方法来处理它。这甚至可能吗?

3 个答案:

答案 0 :(得分:2)

问题是你在调用run方法之前分配数据上下文,这意味着当你分配数据上下文时“MyProgress”对象是“Null”..所以在调用“Run”方法之前数据上下文为null。你正在调用Run方法,它为“MyProgress”创建一个实例,但由于你的“MyClass”不是“INotifyPropertyChanged”,它无法通知数据上下文更改......

解决方法是:尝试在MyClass的构造函数中创建MyProgress实例..所以在分配数据时,上下文不会为null,并且在run方法中不创建任何实例只需更新status属性..

像这样的东西

public class MyClass
{
  public Progress MyProgress { get; set; }

  public MyClass()
  {
    MyProgress = new Progress();
  }

  public void Run()
  {    
    MyProgress.Status = "Initialising";
    // Do stuff, update progress, etc.
  }
}

答案 1 :(得分:0)

<xctk:BusyIndicator HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="busyIndicator" VerticalAlignment="Stretch" BusyContent="{Binding}">
<xctk:BusyIndicator.BusyContentTemplate>
    <DataTemplate>
        <StackPanel Margin="4">
            <TextBlock Text="{Binding Path=Status}" FontWeight="Bold" HorizontalAlignment="Left" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=BusyIndicator}}"/>
        </StackPanel>
    </DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>

// ...

答案 2 :(得分:0)

这对我有用:

*的.xaml

<xctk:BusyIndicator HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="busyIndicator" VerticalAlignment="Stretch" IsBusy="True">
                <xctk:BusyIndicator.BusyContentTemplate>
                    <DataTemplate>
                        <StackPanel Margin="4">
                            <TextBlock Text="{Binding Path=Test.MyProgress.Status, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" FontWeight="Bold" HorizontalAlignment="Left"/>
                        </StackPanel>
                    </DataTemplate>
                </xctk:BusyIndicator.BusyContentTemplate>
            </xctk:BusyIndicator>

* xaml.cs:

public partial class MainWindow : Window
{
    public MyClass Test { get; set; }

    public MainWindow()
    {
        Test = new MyClass();
        InitializeComponent();
        Test.Run();
    }
}

public class MyClass
{
    public Progress MyProgress { get; set; }

    public void Run()
    {
        MyProgress = new Progress();
        MyProgress.Status = "Initialising";
        // Do stuff, update progress, etc.
    }
}

public class Progress : INotifyPropertyChanged
{
    private string status;

    public string Status
    {
        get { return status; }
        set
        {
            status = value;
            OnPropertyChanged("Status");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}