我添加了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检查器查看元素时,我看到ScrollViewer上的属性应为false
,但我的ViewModel属性仍然为true
。
答案 0 :(得分:0)
我的英语不好,但是我写了这个例子。看这个
[MainWindow.xaml.cs]
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
AnyClass c = new AnyClass();
private void h1_Click(object sender, RoutedEventArgs e)
{
Test = true;
}
private void h2_Click(object sender, RoutedEventArgs e)
{
Test = false;
}
public bool Test
{
get { return (bool)GetValue(TestProperty); }
set
{
SetValue(TestProperty, value);
c.Val = value;
}
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
}
[AnyClass.cs]
class AnyClass
{
private bool val = false;
public bool Val
{
get
{
return val;
}
set
{
val = value;
}
}
}
[mainWindow.xaml]
<Button Click="h1_Click" Content="true">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=hUserControl, Path=Test}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=hUserControl, Path=Test}" Value="False">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Click="h2_Click" Content="false">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=hUserControl, Path=Test}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=hUserControl, Path=Test}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>