Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.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# 附属财产。如何在PropertyChangedCallback中使用SetValue_C#_Wpf_Attached Properties - Fatal编程技术网

C# 附属财产。如何在PropertyChangedCallback中使用SetValue

C# 附属财产。如何在PropertyChangedCallback中使用SetValue,c#,wpf,attached-properties,C#,Wpf,Attached Properties,我需要将焦点设置为ViewModel中UIElement的附加属性。 我已经创建了附加属性,并在PropertyChangedCallback中将焦点设置为UIElement private static void VoySetFocusChanged(DependencyObject o,DependencyPropertyChangedEventArgs e) { if(o是UIElement) { if((bool)e.NewValue) { (o作为UIElement.Focus();

我需要将焦点设置为ViewModel中UIElement的附加属性。 我已经创建了附加属性,并在PropertyChangedCallback中将焦点设置为UIElement

private static void VoySetFocusChanged(DependencyObject o,DependencyPropertyChangedEventArgs e)
{
if(o是UIElement)
{
if((bool)e.NewValue)
{
(o作为UIElement.Focus();
(o作为UIElement).SetValue(VoySetFocusProperty,false);
}
}
}
但我想让它像猎枪里的扳机一样工作。我将“真”设置为在ViewModel中测试。。。 它调用MyAttachedProperties类中的PropertyChangedCallback,将焦点设置为UIElement

((作为UIElement.Focus());
并且ViewModel中的Test值返回false

((o as UIElement).SetValue(VoySetFocusProperty, false);)
一切似乎都很正常,但SetValue不会更改ViewModel中的值

完整代码:

视图:


代码隐藏:

使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
利用制度全球化;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WpfAttachedProperty
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
DataContext=新的ViewModel();
}
}
/// 
///命令类
/// 
公共类DelegateCommand:ICommand
{
私有只读操作\u操作;
公共委托人命令(操作)
{
_行动=行动;
}
public void Execute(对象参数)
{
_动作();
}
公共布尔CanExecute(对象参数)
{
返回true;
}
公共事件事件处理程序CanExecuteChanged
{
添加
{
}
去除
{
}
}
}
/// 
///ViewModelClass
/// 
公共类视图模型:INotifyPropertyChanged
{
私有布尔检验=假;
公共布尔测试
{
得到
{
回归检验;
}
设置
{
_测试=数值;
本条。NotifyPropertyChanged(“测试”);
}
}
公共ICommand MyCommand
{
得到
{
返回新的DelegateCommand(SetTestToTrue);
}
}
私有void SetTestToTrue()
{
这个.Test=true;
}
#区域inotifyproperty已更改
public void NotifyPropertyChanged(字符串PropertyName)
{
if(this.PropertyChanged!=null)
{
this.PropertyChanged(this,newpropertychangedventargs(PropertyName));
}
}
公共事件属性更改事件处理程序属性更改;
#端区
}
公共类MyAttachedProperties
{
公共静态对象GetVoySetFocus(DependencyObject obj)
{
返回(对象)obj.GetValue(VoySetFocusProperty);
}
公共静态void SetVoySetFocus(DependencyObject对象,对象值)
{
对象设置值(VoySetFocusProperty,值);
}
公共静态只读从属属性VoySetFocusProperty=
DependencyProperty.RegisterAttached(“VoySetFocus”、typeof(bool)、typeof(MyAttachedProperties)、新UIPropertyMetadata(false、新PropertyChangedCallback(VoySetFocusChanged)、新强制EvalueCallback(强制EvolyseTFocus));
私有静态对象强制EvolyseTFocus(DependencyObject d,object baseValue)
{
返回(bool)基值;
}
私有静态void VoySetFocusChanged(DependencyObject o,DependencyPropertyChangedEventArgs e)
{
if(o是UIElement)
{
if((bool)e.NewValue)
{
(o作为UIElement.Focus();
//在ViewModel中不将测试设置为false
(o作为UIElement).SetValue(VoySetFocusProperty,false);
}
}
}
}
}

你好,马克。

问题在于:

((o as UIElement).SetValue(VoySetFocusProperty, false);)
您应该改为使用设置DP

((o as UIElement).SetCurrentValue(VoySetFocusProperty, false);)
说明

直接设置任何DependencyProperty的值会破坏它与源属性的绑定

(o as UIElement).Focus();
Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate
{
    // Doesn't set Test to false in ViewModel
    (o as UIElement).SetCurrentValue(VoySetFocusProperty, false);
});
但是,
SetCurrentValue
不会中断绑定并将值推回源属性。MSDN对SetCurrentValue的解释如下:

此方法由以编程方式设置 在不禁用应用程序的 声明使用属性。SetCurrentValue方法更改 属性的有效值,但现有触发器、数据绑定、, 而且样式将继续有效


此外,我认为在
PropertyChanged
callback中设置它不会将其传播回Viewmodel,如果同步执行该操作,因为它只能从Viewmodel属性setter到达回调

因此,我们可以通过使用
BeginInvoke
将该操作排队到dispatcher上,从而异步地执行该操作,从而使其获得propagate to viewmodel Test属性

(o as UIElement).Focus();
Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate
{
    // Doesn't set Test to false in ViewModel
    (o as UIElement).SetCurrentValue(VoySetFocusProperty, false);
});

但我还想将ViewModel中的Test设置为false,因为它不是在(o作为UIElement)之后设置的;因为模式是双向绑定。它会自动将值推送到源代码。我想我不明白您的答案。应该如何更改以使其按我希望的方式工作?从ViewModel中的codeBehind changes测试调用SetCurrentValue。它在PropertyChangedCallback@tomatino-我已经更新了我的答案。请如果能解决您的问题,请接受它。祝您愉快:)