GUI xüsusiyyətlərini oxumaq üçün yalnız ViewModel'e basmaqla

ReadModel yazmaq istəyirəm ki, həmişə oxumaq baxımdan bəzi asılılıq xüsusiyyətlərinin mövcud vəziyyətini bilir.

Xüsusilə, GUI'm FlowDocumentPageViewer, FlowDocument-dən birdə bir səhifə göstərəndir. FlowDocumentPageViewer CanGoToPreviousPage və CanGoToNextPage adlanan iki oxunuşlu asılılıq xüsusiyyətləri təmin edir. Mənim ViewModel həmişə bu iki View xüsusiyyətlərinin dəyərlərini bilmək istəyirəm.

Mən bunu OneWayToSource data məcburi ilə edə biləcəyimi qərara aldım:

 <FlowDocumentPageViewer CanGoToNextPage="{Binding NextPageAvailable, Mode=OneWayToSource}" ...> 

Buna icazə verildikdə, yaxşı olardı: FlowGocumentPageViewer CanGoToNextPage mülkinin dəyişdiyi zaman, yeni dəyər mənim istədiyim tam olan ViewModel NextPageAvailable xüsusiyyətinə ötürülür.

Təəssüf ki, bu kompilyasiya edilməyəcək: Mən səhv mesajı alıram: CanGoToPreviousPage özelliği salt okunur ve işaretlemeden ayarlanamaz. Görünür olaraq, yalnız oxunan xassələr bu xüsusiyyətə bağlanan oxunan bir məlumatın deyil, hər hansı bir məlumatın bağlanmasını dəstəkləmir.

Mənim ViewModel DependencyProperties xüsusiyyətlərini edə bilər və OneWay-ı fərqli bir şəkildə bağlaya bilərəm, amma bölüşdürməmə haqqında deli deyiləm (ViewModel üçün, MVVM məlumatların bağlanmasının qarşısını almaq üçün görünüşə istinad etməlisiniz).

FlowDocumentPageViewer, CanGoToNextPageChanged hadisəsini açıqlamır və mən DependencyProperty-dən dəyişiklik bildirişlərini lazımsız görünən birləşdirmək üçün başqa DependencyProperty yaratmadan yaxşı bir şəkildə bilmirəm.

ViewModel görünümümdeki salt okunur görünüm özelliklerini nasıl değiştirebilirim?

115
05 июля '09 в 3:14 2009-07-05 03:14 Joe White istədi 05 iyul '09 3:14 2009-07-05 03:14
@ 6 cavablar

Bəli, keçmişdə ActualWidthActualHeight ilə ActualWidth . ObservedWidthObservedHeight əlavə xüsusiyyətləri olan əlavə davranış yaratdım. Bundan əlavə, ilk Observe üçün istifadə edilən Observe əmlak da var. İstifadəsi aşağıdakılardır:

 public static class SizeObserver { public static readonly DependencyProperty ObserveProperty = DependencyProperty.RegisterAttached( "Observe", typeof(bool), typeof(SizeObserver), new FrameworkPropertyMetadata(OnObserveChanged)); public static readonly DependencyProperty ObservedWidthProperty = DependencyProperty.RegisterAttached( "ObservedWidth", typeof(double), typeof(SizeObserver)); public static readonly DependencyProperty ObservedHeightProperty = DependencyProperty.RegisterAttached( "ObservedHeight", typeof(double), typeof(SizeObserver)); public static bool GetObserve(FrameworkElement frameworkElement) { frameworkElement.AssertNotNull("frameworkElement"); return (bool)frameworkElement.GetValue(ObserveProperty); } public static void SetObserve(FrameworkElement frameworkElement, bool observe) { frameworkElement.AssertNotNull("frameworkElement"); frameworkElement.SetValue(ObserveProperty, observe); } public static double GetObservedWidth(FrameworkElement frameworkElement) { frameworkElement.AssertNotNull("frameworkElement"); return (double)frameworkElement.GetValue(ObservedWidthProperty); } public static void SetObservedWidth(FrameworkElement frameworkElement, double observedWidth) { frameworkElement.AssertNotNull("frameworkElement"); frameworkElement.SetValue(ObservedWidthProperty, observedWidth); } public static double GetObservedHeight(FrameworkElement frameworkElement) { frameworkElement.AssertNotNull("frameworkElement"); return (double)frameworkElement.GetValue(ObservedHeightProperty); } public static void SetObservedHeight(FrameworkElement frameworkElement, double observedHeight) { frameworkElement.AssertNotNull("frameworkElement"); frameworkElement.SetValue(ObservedHeightProperty, observedHeight); } private static void OnObserveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { var frameworkElement = (FrameworkElement)dependencyObject; if ((bool)e.NewValue) { frameworkElement.SizeChanged += OnFrameworkElementSizeChanged; UpdateObservedSizesForFrameworkElement(frameworkElement); } else { frameworkElement.SizeChanged -= OnFrameworkElementSizeChanged; } } private static void OnFrameworkElementSizeChanged(object sender, SizeChangedEventArgs e) { UpdateObservedSizesForFrameworkElement((FrameworkElement)sender); } private static void UpdateObservedSizesForFrameworkElement(FrameworkElement frameworkElement) { // WPF 4.0 onwards frameworkElement.SetCurrentValue(ObservedWidthProperty, frameworkElement.ActualWidth); frameworkElement.SetCurrentValue(ObservedHeightProperty, frameworkElement.ActualHeight); // WPF 3.5 and prior ////SetObservedWidth(frameworkElement, frameworkElement.ActualWidth); ////SetObservedHeight(frameworkElement, frameworkElement.ActualHeight); } } 
142
05 июля '09 в 12:14 2009-07-05 12:14 cavab Kent Boogaart tərəfindən 05.07.2009 12:14 tarixində saat 05: 09-da verilir

Mən yalnız ActualWidth və ActualHeight ilə işləyən, həm də oxuduğunuz rejimdə əlaqələndirə biləcək hər hansı bir məlumatla işləyən universal bir həll istifadə edirəm.

ViewportWidth və ViewportHeight görünüş modeli xüsusiyyətləri olduqda, markup bu kimi görünür.

 <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> 
border=0

Xüsusi elementlər üçün mənbə kodu burada.

53
08 сент. Dmitri Tashkinovun verdiyi cavab 08 sentyabr . 2010-09-08 15:16 '10 da 15:16 'da 2010-09-08 15:16

Kimsə maraqlandığı təqdirdə, mən burada Kent həllinin yaxınlaşdırılmasını kodlaşdırdım:

20
20 авг. 20 Avqustda Scott Whitlock tərəfindən verilmiş cavab 2009-08-20 15:53 '09 da 15:53 ​​'da 2009-08-20 15:53

Burada yazdığım bu "səhv" bir başqa həlldir:
ReadOnly Bağımlılık özelliği üçün OneWayToSource bağlama

İki asılılıq xüsusiyyətindən, dinləyicidən və aynadan istifadə edir. Dinləyici TargetProperty tərəfindən OneWay-a bağlıdır və PropertyChangedCallback onu OneWayToSource ilə Binding-də göstərilənə bağlı olan Mirror əmlakını yeniləyir. Mən bunu PushBinding və bu kimi oxumaq üçün yalnız asılılıq xüsusiyyətinə təyin edilə bilər

 <TextBlock Name="myTextBlock" Background="LightBlue"> <pb:PushBindingManager.PushBindings> <pb:PushBinding TargetProperty="ActualHeight" Path="Height"/> <pb:PushBinding TargetProperty="ActualWidth" Path="Width"/> </pb:PushBindingManager.PushBindings> </TextBlock> 

Demo layihəsini buradan yükləyin .
Bu, mənbə kodunu və nümunənin qısa bir istifadəini ehtiva edir və ya tətbiq haqqında ətraflı məlumat istəyirsinizsə, mənim WPF blogumu ziyarət edir.

Son qeyd, .NET 4.0 olduğundan, hələ də bu dəstəyi dəstəkləyirik, çünki OneWayToSource Binding, yenilənmədən sonra mənbədən dəyər oxuyur

10
29 авг. Cavab Fredrik Hedblad 29 avqustda verilir . 2011-08-29 03:00 '11 saat 03:00 'da 2011-08-29 03:00' də

Dmitri Tashkinovun qərarını sevirəm! Lakin, dizayn rejimində VS-ni sındırdı. Buna görə OnSourceChanged metoduna bir simli əlavə etdim:

 özəl statik boşluq OnSourceChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) { əgər (! ((Bool) DesignerProperties.IsInDesignModeProperty.GetMetadata (typeof (DependencyObject)) DefaultValue)) ((DataPipe) d) .OnSourceChanged (e); }
4
04 окт. Cavab Dariusz Wasacz 04 oktyabr tərəfindən verilir . 2012-10-04 16:34 '12 at 4:34 pm 2012-10-04 16:34

Hesab edirəm ki, bu bir az daha asan edilə bilər:

XAML:

 behavior:ReadOnlyPropertyToModelBindingBehavior.ReadOnlyDependencyProperty="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" behavior:ReadOnlyPropertyToModelBindingBehavior.ModelProperty="{Binding MyViewModelProperty}" 

CS:

Data etiketləri və ya suallar