gpt4 book ai didi

c# - 附属属性(property)。如何在 PropertyChangedCallback 中使用 SetValue

转载 作者:太空狗 更新时间:2023-10-30 01:04:45 27 4
gpt4 key购买 nike

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

private static void VoySetFocusChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (o is UIElement)
{
if ((bool)e.NewValue)
{
(o as UIElement).Focus();
(o as UIElement).SetValue(VoySetFocusProperty, false);
}
}
}

但我希望它像霰弹枪中的扳机一样工作。我在 ViewModel 中将 True 设置为 Test ... 它调用 MyAttachedProperties 类中的 PropertyChangedCallback,将焦点设置到 UIElement

((o as UIElement).Focus();

ViewModel中Test的值返回false

((o as UIElement).SetValue(VoySetFocusProperty, false);)

似乎一切正常,但 SetValue 并没有改变我在 ViewModel 中的值。

完整代码:

查看:

<Window x:Class="WpfAttachedProperty.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfAttachedProperty"
Title="MainWindow" Height="127" Width="316">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBox local:MyAttachedProperties.VoySetFocus="{Binding Path=Test,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Text="Focus Me"/>
<Button Grid.Row="1" Content="Click to Focus" HorizontalAlignment="Left" Margin="10" VerticalAlignment="Top" Width="75" Command="{Binding MyCommand}" />
</Grid>

代码隐藏:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfAttachedProperty
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow:Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}

/// <summary>
/// Command Class
/// </summary>
public class DelegateCommand:ICommand
{
private readonly Action _action;

public DelegateCommand(Action action)
{
_action = action;
}

public void Execute(object parameter)
{
_action();
}

public bool CanExecute(object parameter)
{
return true;
}

public event EventHandler CanExecuteChanged
{
add
{
}
remove
{
}
}
}

/// <summary>
/// ViewModelClass
/// </summary>
public class ViewModel:INotifyPropertyChanged
{
private bool _test = false;
public bool Test
{
get
{
return _test;
}
set
{
_test = value;
this.NotifyPropertyChanged("Test");
}
}
public ICommand MyCommand
{
get
{
return new DelegateCommand(SetTestToTrue);
}
}
private void SetTestToTrue()
{
this.Test = true;
}

#region INotifyPropertyChanged
public void NotifyPropertyChanged(String PropertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}


public class MyAttachedProperties
{
public static Object GetVoySetFocus(DependencyObject obj)
{
return (Object)obj.GetValue(VoySetFocusProperty);
}

public static void SetVoySetFocus(DependencyObject obj, Object value)
{
obj.SetValue(VoySetFocusProperty, value);
}

public static readonly DependencyProperty VoySetFocusProperty =
DependencyProperty.RegisterAttached("VoySetFocus", typeof(bool), typeof(MyAttachedProperties), new UIPropertyMetadata(false, new PropertyChangedCallback(VoySetFocusChanged), new CoerceValueCallback(CoerceVoySetFocus)));

private static object CoerceVoySetFocus(DependencyObject d, object baseValue)
{
return (bool)baseValue;
}

private static void VoySetFocusChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (o is UIElement)
{
if ((bool)e.NewValue)
{
(o as UIElement).Focus();
// Doesn't set Test to false in ViewModel
(o as UIElement).SetValue(VoySetFocusProperty, false);
}
}
}
}
}

问候马可。

最佳答案

问题出在线路上:

((o as UIElement).SetValue(VoySetFocusProperty, false);)

您应该改用 SetCurrentValue 设置 DP。

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

解释:

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

但是,SetCurrentValue 不会破坏绑定(bind)并将值推回到源属性。 MSDN 对 SetCurrentValue 的解释:

This method is used by a component that programmatically sets the value of one of its own properties without disabling an application's declared use of the property. The SetCurrentValue method changes the effective value of the property, but existing triggers, data bindings, and styles will continue to work.


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

因此,我们可以做的是异步执行此操作,方法是使用 BeginInvoke 将它排入调度程序,以便它传播到 viewmodel 测试属性。

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

关于c# - 附属属性(property)。如何在 PropertyChangedCallback 中使用 SetValue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21863715/

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