将只读GUI属性推回ViewModel我想要写一个视图模型,它总是知道视图中某些只读依赖属性的当前状态。具体来说,我的GUI包含一个FlowDocumentPageViewer,它每次从FlowDocument中显示一个页面。FlowDocumentPageViewer公开了两个名为CanGoToPreviousPage和CanGoToNextPage的只读依赖项属性。我希望我的ViewModel始终知道这两个View属性的值。我想我可以通过OneWayToSource数据库实现这一点:<FlowDocumentPageViewer
CanGoToNextPage="{Binding NextPageAvailable, Mode=OneWayToSource}" ...>如果允许这样做,它将是完美的:每当FlowDocumentPageViewer的CanGoToNextPage属性更改时,新的值将被向下推到ViewModel的NextPageAvailable属性中,这正是我想要的。不幸的是,这不能编译:我收到一个错误的说法“CanGoToPreviousPage”属性是只读的,不能从标记中设置。显然只读属性不支持任何这是一种数据绑定,甚至不是针对该属性的只读数据。我可以将ViewModel的属性变成DependencyProperties,并使OneWay绑定向相反的方向发展,但我并不热衷于关注点冲突的分离(ViewModel需要引用视图,MVVM数据库应该避免这种情况)。FlowDocumentPageViewer不公开CanGoToNextPageChanged事件,而且我也不知道从DependencyProperty获取更改通知的任何好方法,除非创建另一个DependencyProperty来绑定它,这在这里似乎有点过分。如何将视图只读属性的更改通知ViewModel?
3 回答
慕姐4208626
TA贡献1852条经验 获得超7个赞
<Canvas> <u:DataPiping.DataPipes> <u:DataPipeCollection> <u:DataPipe Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualWidth}" Target="{Binding Path=ViewportWidth, Mode=OneWayToSource}"/> <u:DataPipe Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualHeight}" Target="{Binding Path=ViewportHeight, Mode=OneWayToSource}"/> </u:DataPipeCollection> </u:DataPiping.DataPipes><Canvas>
public class DataPiping{ #region DataPipes (Attached DependencyProperty) public static readonly DependencyProperty DataPipesProperty = DependencyProperty.RegisterAttached("DataPipes", typeof(DataPipeCollection), typeof(DataPiping), new UIPropertyMetadata(null)); public static void SetDataPipes(DependencyObject o, DataPipeCollection value) { o.SetValue(DataPipesProperty, value); } public static DataPipeCollection GetDataPipes(DependencyObject o) { return (DataPipeCollection)o.GetValue(DataPipesProperty); } #endregion}public class DataPipeCollection : FreezableCollection<DataPipe>{}public class DataPipe : Freezable{ #region Source (DependencyProperty) public object Source { get { return (object)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(object), typeof(DataPipe), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnSourceChanged))); private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataPipe)d).OnSourceChanged(e); } protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e) { Target = e.NewValue; } #endregion #region Target (DependencyProperty) public object Target { get { return (object)GetValue(TargetProperty); } set { SetValue(TargetProperty, value); } } public static readonly DependencyProperty TargetProperty = DependencyProperty.Register("Target", typeof(object), typeof(DataPipe), new FrameworkPropertyMetadata(null)); #endregion protected override Freezable CreateInstanceCore() { return new DataPipe(); }}
青春有我
TA贡献1784条经验 获得超8个赞
class SizeObserver{ #region " Observe " public static bool GetObserve(FrameworkElement elem) { return (bool)elem.GetValue(ObserveProperty); } public static void SetObserve( FrameworkElement elem, bool value) { elem.SetValue(ObserveProperty, value); } public static readonly DependencyProperty ObserveProperty = DependencyProperty.RegisterAttached("Observe", typeof(bool), typeof(SizeObserver), new UIPropertyMetadata(false, OnObserveChanged)); static void OnObserveChanged( DependencyObject depObj, DependencyPropertyChangedEventArgs e) { FrameworkElement elem = depObj as FrameworkElement; if (elem == null) return; if (e.NewValue is bool == false) return; if ((bool)e.NewValue) elem.SizeChanged += OnSizeChanged; else elem.SizeChanged -= OnSizeChanged; } static void OnSizeChanged(object sender, RoutedEventArgs e) { if (!Object.ReferenceEquals(sender, e.OriginalSource)) return; FrameworkElement elem = e.OriginalSource as FrameworkElement; if (elem != null) { SetObservedWidth(elem, elem.ActualWidth); SetObservedHeight(elem, elem.ActualHeight); } } #endregion #region " ObservedWidth " public static double GetObservedWidth(DependencyObject obj) { return (double)obj.GetValue(ObservedWidthProperty); } public static void SetObservedWidth(DependencyObject obj, double value) { obj.SetValue(ObservedWidthProperty, value); } // Using a DependencyProperty as the backing store for ObservedWidth. This enables animation, styling, binding, etc... public static readonly DependencyProperty ObservedWidthProperty = DependencyProperty.RegisterAttached("ObservedWidth", typeof(double), typeof(SizeObserver), new UIPropertyMetadata(0.0)); #endregion #region " ObservedHeight " public static double GetObservedHeight(DependencyObject obj) { return (double)obj.GetValue(ObservedHeightProperty); } public static void SetObservedHeight(DependencyObject obj, double value) { obj.SetValue(ObservedHeightProperty, value); } // Using a DependencyProperty as the backing store for ObservedHeight. This enables animation, styling, binding, etc... public static readonly DependencyProperty ObservedHeightProperty = DependencyProperty.RegisterAttached("ObservedHeight", typeof(double), typeof(SizeObserver), new UIPropertyMetadata(0.0)); #endregion}
添加回答
举报
0/150
提交
取消