附加属性未更新它绑定到的值 (MVVM)

Posted

技术标签:

【中文标题】附加属性未更新它绑定到的值 (MVVM)【英文标题】:Attached property is not updating the value it is bind to (MVVM) 【发布时间】:2021-12-12 01:51:43 【问题描述】:

我有一个用绿色矩形填充的 ScrollViewer,我需要在每次更改时在 TextBlock 上报告它的滚动值(或百分比)。我还需要能够通过更改绑定到的属性来更改滚动值。

我创建了一个附加属性ScrollViewerBehavior,它为我提供了我需要的值,我将它绑定到我的视图模型(ScrollValue)的一个属性,但是该值没有更新,因为设置器永远不会到达。视图模型与视图正确链接。

这是我的代码: 查看

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="6*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <ScrollViewer Grid.Row="0" Background="Gray" local:ScrollViewerBehavior.ScrollState="Binding ScrollValue, Mode=TwoWay" >
        <StackPanel>
            <Rectangle Width="50" Height="50" Fill="Green" Margin="5" />
            <Rectangle Width="50" Height="50" Fill="Green" Margin="5" />
            <Rectangle Width="50" Height="50" Fill="Green" Margin="5" />
            <Rectangle Width="50" Height="50" Fill="Green" Margin="5" />
            <Rectangle Width="50" Height="50" Fill="Green" Margin="5" />
        </StackPanel>
    </ScrollViewer>

    <TextBlock Grid.Row="1" Text="Binding ScrollValue" />
</Grid>

视图模型

public class MainViewModel : BaseViewModel

    private double _scrollValue = 0;
    public double ScrollValue
    
        get  return _scrollValue; 
        set
        
            // This code is never reached 
            _scrollValue = value;
            OnPropertyChanged("ScrollValue");
        
    

ScrollViewerBehavior

    public static double GetScrollState(DependencyObject obj)
    
        return (double)obj.GetValue(ScrollStateProperty);
    

    public static void SetScrollState(DependencyObject obj, double value)
    
        obj.SetValue(ScrollStateProperty, value);
    

    public static readonly DependencyProperty ScrollStateProperty =
        DependencyProperty.RegisterAttached("ScrollState", typeof(double), typeof(ScrollViewerBehavior), new PropertyMetadata(0.5, (o, e) =>
        
            var scrollViewer = o as ScrollViewer;
            
            if (scrollViewer == null)
            
                return;
            
            else
            
                double newVO = (double)e.NewValue * scrollViewer.ScrollableHeight;
                scrollViewer.ScrollToVerticalOffset(newVO);
                SetScrollState(o, newVO);
            
        ));

我看不到我错过了什么

【问题讨论】:

没有真正深入了解它:您确实在某处设置了 DataContext 吗? 可以,直接在视图的构造函数中设置 请注意,if (scrollViewer == null) return; else ... 看起来很奇怪。应该是if (scrollViewer != null) ... 。除此之外,在 ScrollState 属性的 PropertyChanged 处理程序中调用 SetScrollState 是没有意义的。您应该在 ScrollViewer 滚动时设置属性。 【参考方案1】:

我在代码中没有看到您更改ScrollValue 值的任何地方。由于您的附加属性绑定到此,因此它仅在您的视图模型中的ScrollValue 更新时更新。除非我误解了您的解释,否则您希望在每次滚动条值更改时更新ScrollValue。为此,您可以挂钩ScrollChanged 事件:

(我只更新了你的代码只是显示需要什么)

public static readonly DependencyProperty ScrollStateProperty =
    DependencyProperty.RegisterAttached("ScrollState", typeof(double), typeof(ScrollViewerBehavior), new PropertyMetadata(0.5, (o, e) =>
        
            if (o is ScrollViewer scrollViewer)
            
                scrollViewer.ScrollChanged += OnScrollChanged;
            
        ));

    private static void OnScrollChanged(object sender, ScrollChangedEventArgs e)
    
        if (sender is ScrollViewer scrollViewer)
        
            SetScrollState(scrollViewer, scrollViewer.VerticalOffset);
        
    

【讨论】:

以上是关于附加属性未更新它绑定到的值 (MVVM)的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI @State 数组未更新在 init() 期间附加的值

XAML:DependecyObject上的属性在附加集合中的项目时不会更新

XAML:DependecyObject 上的属性在它是附加集合中的项目时不会更新

WPF 高级篇 MVVM 附加属性

WPF 利用附加属性创建FreezableCollection集合和反射实现控件参数以MVVM模式传递

WPF 附加属性数据绑定