gpt4 book ai didi

.net - PropertyChangedCallback 执行的顺序

转载 作者:行者123 更新时间:2023-12-03 10:51:48 25 4
gpt4 key购买 nike

我有一个用户控件,它有两个 DependencyProperties。每个 DependencyProperty 都有 PropertyChangedCallback。在设置属性值的顺序中调用回调很重要。所以如果我写

Status = MyStatus.DataIsImporting;

var data = AsynchronouslyImportData();

Data = data;

我希望在 Data 的属性更改回调之前调用 Status 的属性更改回调。但是根据调试(找不到任何有关它的文档),回调调用的顺序是未定义的。有什么办法可以解决吗?

更新。 您在上面看到的状态和数据并未直接设置为用户控件实例。这些是 ViewModel 属性,它们通过绑定(bind)对用户控制属性。

更新2 .我现在正在处理这个问题并且有一个非常奇怪的修复。以下是我之前使用用户控件的方式:
<MyUserControl Status={Binding Status, Mode=TwoWay} Data={Binding Data}/>

我刚刚更改了绑定(bind)顺序,它起作用了!
<MyUserControl Data={Binding Data} Status={Binding Status, Mode=TwoWay}/>

它仍然以异步方式运行(看起来绑定(bind)系统内部存在某种消息循环),但现在它以正确的顺序调用 PropertyChangedCallback 处理程序。

我在谷歌上搜索绑定(bind)顺序,不时发现类似的问题(例如, this one),但仍不清楚为什么会发生。

更新 3。我找到了真正的问题根源。使用我的控件的应用程序具有带有多个 DataTemplates 的 ContentControl(取决于 ViewModel 类型)。当我的控件所在的 DataTemplate 不是当前的(或者当您切换到其他 DataTemplate 并返回时),就会发生所描述的行为。我仍在澄清细节。

最佳答案

我可能应该用这个陈述来作为这个答案的开头:

“如果您需要通过排列/排序 DependencyProperty 的顺序来对 DependencyPropertyChangedCallbacks 所做的更改进行排序,那么您可能做错了。”

也就是说,这里有一些闲置的代码,有点像你在说的那样:

物体:

public class SomeThing : DependencyObject, IDisposable
{
public static readonly DependencyProperty StatusProperty =
DependencyProperty.Register(
"Status",
typeof(string),
typeof(SomeThing),
new FrameworkPropertyMetadata(OnStatusChanged));
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register(
"Data",
typeof(string),
typeof(SomeThing),
new FrameworkPropertyMetadata(OnDataChanged));

// The OrderedBag is from the Wintellect.PowerCollections,
// as I was too lazy to write my own PriorityQueue-like implementation
private static OrderedBag<Tuple<int, DependencyObject, DependencyPropertyChangedEventArgs>> _changeQueue =
new OrderedBag<Tuple<int, DependencyObject, DependencyPropertyChangedEventArgs>>((l,r) => l.Item1.CompareTo(r.Item1));

private static object _syncRoot = new object();
private static Task queueTenderTask;
private static CancellationTokenSource canceller;

static SomeThing()
{
canceller = new CancellationTokenSource();
queueTenderTask = Task.Factory.StartNew(queueTender);
}

public string Status
{
get { return (string)this.GetValue(StatusProperty); }
set { this.SetValue(StatusProperty, value); }
}
public string Data
{
get { return (string)this.GetValue(DataProperty); }
set { this.SetValue(DataProperty, value); }
}

public void Dispose()
{
if(canceller != null)
{
canceller.Cancel();
if(queueTenderTask != null)
{
queueTenderTask.Wait();
}
}
}

private static void OnStatusChanged(
DependencyObject dobj,
DependencyPropertyChangedEventArgs args)
{
lock(_syncRoot)
{
_changeQueue.Add(Tuple.Create(0, dobj, args));
}
}
private static void OnDataChanged(
DependencyObject dobj,
DependencyPropertyChangedEventArgs args)
{
lock(_syncRoot)
{
_changeQueue.Add(Tuple.Create(1, dobj, args));
}
}
private static void ProcessChange(
Tuple<int, DependencyObject,DependencyPropertyChangedEventArgs> pair)
{
// do something useful?
Console.WriteLine(
"Processing change on {0} from {1} to {2}",
pair.Item3.Property.Name,
pair.Item3.OldValue,
pair.Item3.NewValue);
}

private static void queueTender()
{
Console.WriteLine("Starting queue tender...");
var shouldCancel = canceller.IsCancellationRequested;
while(!shouldCancel)
{
lock(_syncRoot)
{
if(_changeQueue.Count > 0)
{
var nextUp = _changeQueue[0];
_changeQueue.RemoveFirst();
ProcessChange(nextUp);
}
}
for(int i=0;i<10;i++)
{
shouldCancel = canceller.IsCancellationRequested;
if(shouldCancel) break;
Thread.Sleep(10);
}
}
}
}

和测试:

void Main()
{
var rnd = new Random();
using(var ob = new SomeThing())
{
for(int i=0;i<10;i++)
{
if(rnd.NextDouble() > 0.5)
{
Console.WriteLine("Changing Status...");
ob.Status = rnd.Next(0, 100).ToString();
}
else
{
Console.WriteLine("Changing Data...");
ob.Data = rnd.Next(0, 100).ToString();
}
}
Console.ReadLine();
}
}

输出:

开始排队招标...
更改状态...
更改状态...
更改状态...
更改数据...
更改数据...
更改数据...
更改数据...
更改数据...
更改数据...
更改状态...
处理状态从到 1 的更改
处理状态从 1 到 73 的更改
处理状态从 73 到 57 的更改
处理状态从 57 到 33 的更改
处理从数据到 10 的更改
处理数据从 10 到 67 的变化
处理数据从 67 到 40 的变化
处理数据从 40 到 64 的变化
处理数据从 64 到 47 的变化
处理数据从 47 到 81 的变化

关于.net - PropertyChangedCallback 执行的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15482340/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com