C# 应用程序启动时附加的属性回调事件为控件属性绑定返回null
故事与问题: 我将IsActivated属性创建为附加属性,以便能够将其添加到我想要的XAML页面中的任何控件中。然后,当任何控件将其设置为true时,我希望触发PropertyChangedCallback事件并检查该控件特定属性的绑定。应用程序运行时没有任何问题,而且所有将IsActivated属性设置为true的控件都将触发该事件,binding对象也会在UI中正确显示该值 但问题是,当PropertyChangedcallback事件执行时,GetBinding或GetBindingExpression方法将为这些属性返回null值 现在我只检查TextBox及其TextProperty 背景&我已经尝试过的 我在我的生产应用程序中使用了相同的技术,但当我试图简化它以向朋友演示时,它不起作用 我发现,如果我在MainWindow.OnLoaded事件中为TextBox设置/更改IsActivated属性,则在其回调事件中,它将正确返回TextBox.TextProperty的绑定信息: private void OnLoadedobject发送方,RoutedEventArgs e { MyTextBox.SetValueChangeBehavior.IsActivatedProperty,false; } 但我没有在我真正的应用程序中这样做,我不喜欢这个解决方案 源代码 这是完整的示例代码 但这里是我附加的属性类: 公共静态类变更行为 { 公共静态只读从属属性为ActivatedProperty; 静态变化行为 { IsActivatedProperty=DependencyProperty.RegisterAttached 我被激活了, 池的类型, 改变行为的类型, 新属性MetadataFalse,OnIsActivatedPropertyChangedCallback ; } 公共静态bool GetIsActivatedPendencyObject obj =>boolobj.GetValueIsActivatedProperty; 公共静态void setIsActivatedPendencyObject对象,布尔值 =>obj.SetValueIsActivatedProperty,value; 私有静态无效仅限于ActivatedPropertyChangedCallbackDependencyObject d,DependencyPropertyChangedEventArgs e { 如果!d是文本框返回; //=>这里我得到空值 var binding=BindingOperations.getbinding,TextBox.TextProperty; 如果binding==null返回; 如果boole.NewValue { var sourceObject=binding.Path.Path; //做一些事情。。。 } 其他的 { //做一些事情。。。 } } } 这是我的UI XAML: 主窗口代码隐藏: 公共部分类主窗口:窗口 { 私有只读视图模型_ViewModel; 公共主窗口视图模型视图模型 { 初始化组件; _viewModel=viewModel; DataContext=_viewModel; } } ViewModel类:忽略NotifyProperty。。。把它分成两部分使它变短C# 应用程序启动时附加的属性回调事件为控件属性绑定返回null,c#,wpf,xaml,binding,attached-properties,C#,Wpf,Xaml,Binding,Attached Properties,故事与问题: 我将IsActivated属性创建为附加属性,以便能够将其添加到我想要的XAML页面中的任何控件中。然后,当任何控件将其设置为true时,我希望触发PropertyChangedCallback事件并检查该控件特定属性的绑定。应用程序运行时没有任何问题,而且所有将IsActivated属性设置为true的控件都将触发该事件,binding对象也会在UI中正确显示该值 但问题是,当PropertyChangedcallback事件执行时,GetBinding或GetBindingEx
public class ViewModel : INotifyPropertyChanged
{
private Model _model;
public ViewModel()
{
Model = new Model {Name = "Model One"};
}
public Model Model
{
get => _model;
set
{
_model = value;
OnPropertyChanged();
}
}
public event PropertyChangedEvent...
}
public class Model : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEvent...
}
}
模型类:忽略NotifyProperty。。。把它分成两部分使它变短
public class ViewModel : INotifyPropertyChanged
{
private Model _model;
public ViewModel()
{
Model = new Model {Name = "Model One"};
}
public Model Model
{
get => _model;
set
{
_model = value;
OnPropertyChanged();
}
}
public event PropertyChangedEvent...
}
public class Model : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEvent...
}
}
我的代码怎么了
我希望初始化组件时;从我的主窗口构造函数中执行,就像我的真实应用程序一样,任何在XAML中将local:ChangeBehavior.IsActivated设置为true的控件,我都可以在OnIsActivatedPropertyChangedCallback方法中获得它们属性的正确bindig信息
为什么几乎相同的技术和几乎相同的代码!在我的实际应用程序中工作,但在这个简单的代码中不工作
我错过了什么
更新:解决我的问题的第二种方法是:
我应该在ResourceDictionary中使用IsAttached属性,而不是直接在元素上使用它。另一种方式是,我将其标记为“答案”我想看看这在您的实际项目中的应用情况。在本例中,它是在文本上设置绑定之前设置的。永远不要让附加属性依赖于初始化顺序,因为这完全超出了您的控制范围 我们想做的是:如果我们能做到,就去做。如果没有,请在加载控件后执行,除非它已经加载,在这种情况下,几乎肯定不会有任何事情要做。在加载的处理程序中这样做是可以的,因为类的使用者不必查看它,而b您没有其他选择 理想情况下,每当在文本上设置绑定时,我们都希望这样做,但没有这样的事件,而且在运行时替换绑定是比较少见的
private static void OnIsActivatedPropertyChangedCallback(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (d is TextBox textBox)
{
if (!tryGetBinding() && !textBox.IsLoaded)
{
void onLoaded(object sender, RoutedEventArgs e2)
{
tryGetBinding();
textBox.Loaded -= onLoaded;
};
textBox.Loaded += onLoaded;
}
bool tryGetBinding()
{
// ===> Here I get null value
var binding = BindingOperations.GetBinding(textBox, TextBox.TextProperty);
if (binding == null)
return false;
if (GetIsActivated(textBox))
{
var sourceObject = binding.Path.Path;
//Doing some stuff...
}
else
{
//Doing some stuff...
}
return true;
};
}
}
哇!那太好了!!我仍然想知道为什么在我的应用程序中没有这个加载的事件,它还能工作!?当它不在这里工作的时候!?我从@thomascraudiushuber的教程Pluralsight:WPF和MVVM:Advanced Model Treatment中学习了这项技术。我们使用DI在那里注入ViewModels&这是在那里工作的原因吗!!?不管怎样,我相信这是我的错,因为我是托马斯的坏学生!但是你的解决方案很好。我试图找出几个小时的原因&。。。你救了我!非常感谢@先生,我收到了
当我看到你的窗口有一个构造器参数时,会有一种不舒服的感觉,那就是viewmodels正在进行一些奇怪的事情。这是你的生活。我真的很想看到一个背景,在那里它确实以旧的方式工作。它可能在数据模板中吗?我在GitHub上找到了Thomas代码,在这里您可以检查他的完整代码:,我们在FriendStorage.UI\Styles\ControlBaseStyle.cs中的ResourceDictionary中定义了IsActive。你也可以检查这个文件夹:FriendStorage.UI\Behavior\ChangeBehavior,这是我试图简化它的原始文件,但我失败了!现在你有了完整的样品,你能再帮我一个忙吗!?若你们发现为什么托马斯代码的IsActive AttachedProperty在他并没有使用Load事件的情况下工作,请告诉我!高级版谢谢。谢谢你的风格提示!你是对的,我也用风格来测试它,它成功了!非常感谢您的时间,今天我从您那里学到了新的东西,正如我从托马斯教程中学到的很多东西一样。我确信这里所有的过错都在我身上;[坏学生!]再次感谢您,祝您玩得愉快…@MRK非常认真,他应该知道这会是一个问题。他“教”你一些错误的东西。