"必须在与DependencyObject"相同的线程上创建DependencySource。更改SelectedItem时

时间:2017-01-31 13:53:07

标签: c# wpf

我有一个错误"必须在与DependencyObject相同的线程上创建DependencySource"在我的项目中。

我的评论用于加载文件并创建列表。此列表绑定到ListBox。 AL工作得很好。但是我创建了一个要加载的任务(加载可以很长)。现在我有这个错误。我不明白为什么会这样。

有我的代码:

MainView.xaml:

<ListBox ItemsSource="{Binding Results}"
         SelectedItem="{Binding SelectedItem}">
    <ListBox.InputBindings>
        <KeyBinding Command="{Binding RemoveCommand}"
                    Key="Delete"/>
    </ListBox.InputBindings>
</ListBox>

<Button Grid.Row="1" Grid.Column="0"                    
        Style="{StaticResource StyleButton}"
        Command="{Binding LoadCommand}"
        Content="Open result"/>

MainViewModel:

#region Fields/Properties
public ImageWithPoints SelectedItem
{
    get
    {
        return _selectedItem;
    }
    set
    {
        _selectedItem = value;
        SelectedPointIndex = 1;
        OnPropertyChanged();
        OnPropertyChanged("Picture");
        UpdatePoints();
    }
}
        public List<ImageWithPoints> Results
{
    get
    {
        return _results;
    }
    set
    {
        _results = value;
        if (value == null)
        {
            SelectedPointIndex = 0;
        }
        OnPropertyChanged();
    }
}
public BitmapSource Picture
{
    get
    {
        return SelectedItem?.Picture;
    }
}
#endregion
#region Load
private ICommand _loadCommand;
public ICommand LoadCommand
{
    get
    {
        if (_loadCommand == null)
            _loadCommand = new RelayCommand(OnLoad, CanLoad);
        return _loadCommand;
    }
}
public void OnLoad()
{
    StartRunning(this, null);
    Task loadTask = new Task(new Action(() =>
    {
        Load();
        Application.Current.Dispatcher.Invoke(new Action(() =>
        {
            StopRunning(this, null);
        }));
    }));
    loadTask.Start();
}
public bool CanLoad()
{
    return !IsRunning;
}
#endregion
#region Events  
public event EventHandler OnStartRunning;
public event EventHandler OnStopRunning;
private void StartRunning(object sender, EventArgs e)
{
    OnStartRunning(sender, e);
}
private void StopRunning(object sender, EventArgs e)
{
    OnStopRunning(sender, e);
}
#enregion
#region Methods
public void Load()
{
    // Open File
    // Set to list
    List<ImageWithPoints> listRes;
    Results = listRes;
    SelectedItem = Results[0];  
}
#endregion

当我删除该行SelectedItem = Results[0];时,我没有错误(但是应用程序没有工作)。

1 个答案:

答案 0 :(得分:1)

任务完成后,在UI线程上重新设置SelectedItem属性:

public void OnLoad()
{
    StartRunning(this, null);
    Task.Factory.StartNew(new Action(() =>
    {
        Load();
    })).ContinueWith(task =>
    {
        SelectedItem = Results[0];
        StopRunning(this, null);
    }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

您只能访问最初创建它的线程上的UI元素,因此如果您的UpdatePoints()方法访问必须在UI线程上调用此方法的任何控件。