【发布时间】:2018-07-26 20:29:46
【问题描述】:
我添加了一个 ScrollViewer 行为,当基于 Scroll the scrollviewer to top through viewmodel 将属性设置为 true 时,该行为允许我滚动到顶部。我发现这第一次完美运行,但随后的尝试没有触发,因为TwoWay 绑定没有将我的属性设置回false。
这是显示我的问题的简单项目:
MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="200">
<ScrollViewer local:ScrollViewerBehavior.ScrollToTop="{Binding Reset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200"/>
</Grid.RowDefinitions>
<Button VerticalAlignment="Bottom" Content="Top" Command="{Binding Scroll}"/>
</Grid>
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel _ViewModel;
public MainWindow()
{
InitializeComponent();
DataContext = _ViewModel = new ViewModel();
}
}
}
ViewModel.cs
using System;
using System.ComponentModel;
using System.Windows.Input;
namespace WpfApp1
{
public class RelayCommand : ICommand
{
private readonly Action<object> action;
public RelayCommand(Action<object> action)
{
this.action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
action(parameter);
}
}
public class ViewModel : INotifyPropertyChanged
{
private bool _reset = false;
public ViewModel()
{
Scroll = new RelayCommand(o =>
{
Reset = true;
});
}
public event PropertyChangedEventHandler PropertyChanged;
public bool Reset
{
get { return _reset; }
set
{
bool changed = value != _reset;
_reset = value;
if (changed)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Reset)));
}
}
}
public RelayCommand Scroll { get; set; }
}
}
ScrollViewerBehavior.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public static class ScrollViewerBehavior
{
public static readonly DependencyProperty ScrollToTopProperty = DependencyProperty.RegisterAttached("ScrollToTop", typeof(bool), typeof(ScrollViewerBehavior), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, e) =>
{
if (o is ScrollViewer sc)
{
if ((bool)e.NewValue)
{
sc.ScrollToTop();
SetScrollToTop((FrameworkElement)o, false); // this should set the property back to false
}
}
}));
public static bool GetScrollToTop(FrameworkElement o)
{
return (bool)o.GetValue(ScrollToTopProperty);
}
public static void SetScrollToTop(FrameworkElement o, bool value)
{
o.SetValue(ScrollToTopProperty, value);
}
}
}
我知道,如果我取出更改后的房产支票,它会起作用;但是,这对我的情况并不理想。当我通过 WPF Inspector 查看元素时,我看到 ScrollViewer 上的属性应该是 false,但我的 ViewModel 属性仍然是 true。
【问题讨论】:
-
debug找下来?
-
@ThierryV,我已经放了断点,当执行应该将值设置回 false 的代码行时,ViewModel 上没有任何内容。 WPF Inspector 说它已经更新,但我不确定还有什么要调试的。
-
嗨,显然(我在这个问题上绊倒了几次)依赖属性的 Setvalue 方法不会触发 Notifypropertychanged 作为 expexted。也许使用 ' NotifyOnSourceUpdated=True , NotifyOnTargetUpdated=True' 扩展行为的绑定可能会有所帮助(尽管后者不会发生,因为您不会更改绑定控件上的值...)
-
好的,重读节目,你需要更新目标 :)
-
@dba 知道它不会触发事件很有趣。有办法解决吗?