Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 应用程序启动时附加的属性回调事件为控件属性绑定返回null_C#_Wpf_Xaml_Binding_Attached Properties - Fatal编程技术网

C# 应用程序启动时附加的属性回调事件为控件属性绑定返回null

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

故事与问题:

我将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。。。把它分成两部分使它变短

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非常认真,他应该知道这会是一个问题。他“教”你一些错误的东西。