將只讀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 回答
當年話下
TA貢獻1890條經驗 獲得超9個贊
<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();
}}
catspeake
TA貢獻1111條經驗 獲得超0個贊
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}- 3 回答
- 0 關注
- 434 瀏覽
添加回答
舉報
0/150
提交
取消
