RelativeSource ilə WPF bağlamalarını necə istifadə etmək olar?

WPF bağlamaları ilə RelativeSource necə istifadə və müxtəlif istifadə nədir?

520
17 сент. David Schmitt tərəfindən 17 sentyabrda təyin olundu . 2008-09-17 18:10 '08 at 6:10 pm 2008-09-17 18:10
@ 14 cavab

Bir obyekti başqa bir obyektə bağlamaq istəyirsinizsə:

 {Binding Path=PathToProperty, RelativeSource={RelativeSource Self}} 

Bir atadan əmlak almaq istəyirsinizsə:

 {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}} 

Mülkiyyəti ana şablonda almaq istəyirsinizsə (ControlTemplate-də 2 məcburi etiket qura bilərsiniz)

 {Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}} 

və ya qısa (bu yalnız OneWay bağlamalar üçün çalışır):

 {TemplateBinding Path=PathToProperty} 
695
17 сент. 17 sentyabrda Abe Heidebrecht'e cavab verildi. 2008-09-17 18:14 '08 saat 06:14 'da 2008-09-17 18:14
 Binding RelativeSource={ RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType} } ... 

RelativeSource üçün atribut xüsusiyyət atributu Mode . Müvafiq dəyərlərin tam siyahısı ( MSDN-dən ):

border=0
  • ÖncekiData Göstərilən məlumat elementlərinin siyahısında əvvəlki məlumat elementini (məlumatın elementini ehtiva edən yoxlama) bağlamağa imkan verir.

  • TemplatedParent Şablon tətbiq edildiyi elementə istinad edir (məlumatlara bağlı element var). Bu, bir TemplateBindingExtension quruluşuna bənzəyir və yalnız bir cədvəl bir şablon içində olduqda tətbiq olunur.

  • Self Özünüzü bağladığınız bir elementi göstərir və bu elementin bir xüsusiyyətini eyni elementdə başqa bir obyektə bağlamağa imkan verir.

  • FindAncestor Data bağlı maddənin ana zəncirində sələfinə istinad edir. Bunu, müəyyən bir növ və ya alt siniflərin bir atasına bağlamaq üçün istifadə edə bilərsiniz. AncestorType və / və ya AncestorLevel təyin etmək istəyirsinizsə istifadə etdiyiniz rejimi.

122
03 марта '09 в 12:24 2009-03-03 12:24 Cavab Drew Noakes tərəfindən 03.03 'da 03.03' də verildi

Burada MVVM arxitekturası kontekstində daha çox görsel izahat verilir:

2019

113
16 марта '11 в 5:35 2011-03-16 05:35 Cavab Cef K tərəfindən verilir. 16 Mart 'da 5:35' də 2011-03-16 05:35

Təsəvvür edin ki, biz onun hündürlüyünü həmişə onun genişliyinə bərabər, bir kvadrat deyirik ki, düzbucaqlı istəyirik. Bunu element adından istifadə edə bilərik.

 <Rectangle Fill="Red" Name="rectangle" Height="100" Stroke="Black" Canvas.Top="100" Canvas.Left="100" Width="{Binding ElementName=rectangle, Path=Height}"/> 

Lakin bu halda biz məcburi obyektin adını, yəni dikdörtgəni göstərməyi məcburiyyətindəyik. RelativeSource-dan istifadə edərək eyni məqsədə müxtəlif yollarla nail ola bilərik

 <Rectangle Fill="Red" Height="100" Stroke="Black" Width="{Binding RelativeSource={RelativeSource Self}, Path=Height}"/> 

Bu halda, biz anchor obyektinin adını qeyd etmək tələb olunmur və genişlik hər zaman boyu dəyişdikdə yüksəkliyə bərabər olacaqdır.

Width parametresinin yarım yükseklik olması isterseniz, Ciltleme işaretleme uzantısına bir dönüştürücü ekleyerek bunu edə bilərsiniz. Başqa bir vəziyyət düşünün:

  <TextBlock Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}"/> 

Yuxarıdakı vəziyyət, müəyyən bir elementin verilmiş bir əmlakını onun birbaşa valideynlərindən birinə bağlamaq üçün istifadə olunur, çünki bu element əsas adlanan bir əmlakı ehtiva edir. Bu, bizi FindAncestor olan nisbi mənbədən başqa bir üsula aparır.

40
09 нояб. Cavab lasitha edirisooriya 09 noyabr. 2012-11-09 08:47 '12 at 8:47 2012-11-09 08:47

Bechir Bejaoui məqaləsində WPF-də RelativeSources-in istifadəsini müzakirə edir:

RelativeSource, xüsusi bir inkişafın idarə olunması vəziyyətində XAML hissəsi üçün bağımlılıq dəyərinin dəyərini bağladığında, bir obyektin əmlakını başqa bir qohumuna birləşdirməyə çalışdığımızda, obyektin özünün başqa bir əmlakı ilə müəyyən bir obyektin mülkiyyətini obyektiv olaraq birləşdirməyə çalışdığımız bir markup uzadılmasıdır Nəhayət, bir sıra diferensialın istifadə edilməsi halında, əlaqəli məlumatlar. Bütün bu vəziyyətlər nisbi mənbə rejimi kimi ifadə edilir. Bütün bu işlərin bir-birinin ardınca gedəcəyəm.

  • Öz rejimi:

Bu işi istədiyimiz dikdörtgeni düşünün, hündürlüyü həmişə genişliyinə bərabər bir kvadrat söyləyə bilər. Bunu element adından istifadə edə bilərik.

 <Rectangle Fill="Red" Name="rectangle" Height="100" Stroke="Black" Canvas.Top="100" Canvas.Left="100" Width="{Binding ElementName=rectangle, Path=Height}"/> 

Ancaq bu vəziyyətdə, biz anchor obyektinin adını, yəni bir dikdörtgeni göstərməyi məcburiyyətindəyik. Eyni məqsədimizə başqa bir şəkildə RelativeSource istifadə edə bilərik

 <Rectangle Fill="Red" Height="100" Stroke="Black" Width="{Binding RelativeSource={RelativeSource Self}, Path=Height}"/> 

Bu halda, biz birləşdirən obyektin adını qeyd etməməliyik və hündürlük dəyişdikdə genişlik hər zaman yüksəkliyə bərabər olacaqdır.

Genişlik parametresinin yarım boyu olmasını istəyirsinizsə, Binding markup uzantısına bir çevirici ekleyerek bunu edə bilərsiniz. Başqa bir vəziyyət düşünün:

  <TextBlock Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}"/> 

Verilən bir iş, bu elementin bu elementi onun birbaşa valideynlərindən birinə bağlamaq üçün istifadə olunur, çünki bu element əsas müəssisə adlanır. Bu bizə FindAncestor olan başqa bir nisbi mənbə rejiminə gətirir.

  • FindAncestor rejimi

Bu halda, bu elementin əmlakı onun valideynlərindən birinə, Korsika ilə əlaqəli olacaq. Yuxarıdakı hadisədən əsas fərq, əmlakı əlaqələndirmək üçün, hiyerarşidə rütbənin atasının və atasının növünü təyin etməkdir. Yeri gəlmişkən, XAML bu parça ilə oynamaq üçün cəhd edin

 <Canvas Name="Parent0"> <Border Name="Parent1" Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}" Height="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualHeight}"> <Canvas Name="Parent2"> <Border Name="Parent3" Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}" Height="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualHeight}"> <Canvas Name="Parent4"> <TextBlock FontSize="16" Margin="5" Text="Display the name of the ancestor"/> <TextBlock FontSize="16" Margin="50" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Border}, AncestorLevel=2},Path=Name}" Width="200"/> </Canvas> </Border> </Canvas> </Border> </Canvas> 

Yuxarıda göstərilən vəziyyət, hiyerarşik valideynlərini təmsil edən bir sıra sərhəd və kətan elementləri daxilində yerləşdirilən iki TextBlock elementindən ibarətdir. İkinci TextBlock bu valideynin adını nisbi bir mənbə kodu səviyyəsində göstərəcək.

Beləliklə, AncestorLevel = 2-i AncestorLevel = 1-ə dəyişməyə çalışın və nə olacağını görə bilərsiniz. AncestorType = Sərhəddən AncestorType = Canvas üçün əcdadı növünü dəyişdirməyi cəhd edin və nə olacağını görə bilərsiniz.

Göstərilən mətn ata və səviyyəyə uyğun olaraq dəyişəcək. Sonra, ata səviyyəsinin ata növü üçün uyğun deyilsə nə olur? Bu yaxşı bir sual, bilirəm ki, bunu soruşacaqsınız. Cavab çıxarılmayacaq və heç bir şey TextBlock səviyyəsində göstərilməyəcək.

  • TemplatedParent

Bu rejim, ControlTemplate xüsusiyyətinin ControlTemplate tətbiq olunduğuna nəzarət obyektinə bağlamanıza imkan verir. Buradaki problemi anlamaq üçün yaxşı nümunədir.

 <Window.Resources> <ControlTemplate x:Key="template"> <Canvas> <Canvas.RenderTransform> <RotateTransform Angle="20"/> </Canvas.RenderTransform> <Ellipse Height="100" Width="150" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"> </Ellipse> <ContentPresenter Margin="35" Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/> </Canvas> </ControlTemplate> </Window.Resources> <Canvas Name="Parent0"> <Button Margin="50" Template="{StaticResource template}" Height="0" Canvas.Left="0" Canvas.Top="0" Width="0"> <TextBlock FontSize="22">Click me</TextBlock> </Button> </Canvas> 

Bu nəzarətin xüsusiyyətlərini şablon nəzarətinə tətbiq etmək istəyirsinizsə, mən TemplatedParent rejimi istifadə edə bilərsiniz. Birincisi, qısa bir əl növü olan TemplateBinding olan bu markup uzantısına da oxşardır, lakin TemplateBinding ilk dəfə işləndikdən dərhal sonra qiymətləndirilən TemplatedParent kontrastı ilə kompilyasiya zamanı qiymətləndirilir. Göründüyü kimi, aşağıdakı şəklə baxa bilərsiniz, arka plan və məzmun düymədən nəzarət nümunəsinə tətbiq olunur.

34
19 окт. 19 oktyabrda Cornel Marian tərəfindən verilən cavab . 2013-10-19 23:34 '13 at 11:34 pm 2013-10-19 23:34

TemplatedParent'i unutma:

 <Binding RelativeSource="{RelativeSource TemplatedParent}"/> 

və ya

 {Binding RelativeSource={RelativeSource TemplatedParent}} 
17
17 сент. Cavab Bob Kral tərəfindən 17 sentyabrda verilir. 2008-09-17 18:14 '08 saat 06:14 'da 2008-09-17 18:14

WPF RelativeSource bağlamasında, qurmaq üçün üç properties vardır:

1. Mode: bu dörd dəyərə malik olan enum :

a PreviousData ( value=0 ): əvvəlki property dəyərini cildinə verir

b. TemplatedParent ( value=1 ): hər hansı bir nəzarət templates müəyyən etmək və nəzarət dəyərinə / əmlakına bağlamaq üçün istifadə olunur.

Məsələn, bir ControlTemplate :

  <ControlTemplate> <CheckBox IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </ControlTemplate> 

c. Self ( value=2 ): Özümüzə və ya property özümüzü birləşdirmək istəyirik.

Məsələn: Checked State checkbox CommandParameter olaraq CommandParameter , Command -da CheckBox a CommandParameter

 <CheckBox ...... CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=IsChecked}" /> 

e FindAncestor ( value=3 ): Görsel Ağardaki ana control bir bağlama tələb olunduqda.

Məsələn: header checkbox header checkbox , grid içinde ise, records bağlanma checkbox kutusu

 <CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}}, Path=DataContext.IsHeaderChecked, Mode=TwoWay}" /> 

2. AncestorType: rejimi FindAncestor olduqda ata növünü müəyyənləşdirin

 RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}} 

3. FindAncestor rejimi FindAncestor olduğunda, FindAncestor səviyyəsi nədir ( visual tree eyni tipli iki valideyn varsa)

 RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid, AncestorLevel=1}} 

Əvəzində RelativeSource binding istifadə etmək üçün bütün imkanlar var.

İşarədir .

14
21 янв. Cavab Kylo Ren Jan 21 2016-01-21 16:41 '16 saat 16:41 'da 2016-01-21 16:41

RelativeSource istifadə sadələşdirilməsi də daxil olmaqla WPF məcburi sintaksis sadələşdirmək üçün bir kitabxana yaratdı. Burada bəzi nümunələr var. Əvvəllər:

 {Binding Path=PathToProperty, RelativeSource={RelativeSource Self}} {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}} {Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}} {Binding Path=Text, ElementName=MyTextBox} 

Sonra:

 {BindTo PathToProperty} {BindTo Ancestor.typeOfAncestor.PathToProperty} {BindTo Template.PathToProperty} {BindTo #MyTextBox.Text} 

Burada metodun bağlanmasının necə sadələşdirildiyinə dair bir nümunədir. Əvvəllər:

 // C# code private ICommand _saveCommand; public ICommand SaveCommand { get { if (_saveCommand == null) { _saveCommand = new RelayCommand(x => this.SaveObject()); } return _saveCommand; } } private void SaveObject() { // do something } // XAML {Binding Path=SaveCommand} 

Sonra:

 // C# code private void SaveObject() { // do something } // XAML {BindTo SaveObject()} 

Kitabxananı burada tapa bilərsiniz: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html

Mən əvvəlcə RelayCommand istifadə edərək optimallaşdırılmış bir metodu bağlamaq üçün istifadə etdiyim "ƏVVƏL" nümunəsindəki qeyd WPF-nin bir hissəsidir. Bu olmadan "ÖNCE" nümunəsi daha da uzaqdır.

13
06 авг. Luis Perezin Aug 06 tərəfindən verdiyi cavab 2012-08-06 21:12 '12 at 9:12 pm 2012-08-06 21:12

Diqqətə çatdırmaq lazımdır ki, bu düşüncəni Silverlight'a bənzəyənlər üçün:

Silverlight, bu əmrlərin yalnız altkateqoriyasını təklif edir.

13
24 апр. Cavab Matthew Black 24 apr tərəfindən verilir . 2010-04-24 19:02 '10 at 19:02 2010-04-24 19:02

Bəzi faydalı bitlər:

Burada əsasən kodda bunu etmək olar:

Əvəzində bunun Arxiv kodu bağlayıcı nisbi mənbədən köçürdüm . 

Bundan əlavə, MSDN səhifə misal kimi olduqca yaxşıdır: RelativeSource Class

11
30 окт. Cavab Nathan Cooper tərəfindən 30 oktyabrda verilir. 2012-10-30 14:22 '12 saat 14:22 'da 2012-10-30 14:22

Mənim üçün işləyən Silverlight elementindəki elementin DataContext-ə daxil olmaq üçün başqa bir həll qoyduq. Binding ElementName istifadə edir.

10
23 авг. Cavab Juve 23 aug verilir . 2010-08-23 16:05 '10 at 16:05 2010-08-23 16:05

Bu, mənim üçün boş datagrids üzərində işləyən bu şablondan istifadə etmək nümunəsidir.

 <Style.Triggers> <DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0"> <Setter Property="Background"> <Setter.Value> <VisualBrush Stretch="None"> <VisualBrush.Visual> <TextBlock Text="We did't find any matching records for your search..." FontSize="16" FontWeight="SemiBold" Foreground="LightCoral"/> </VisualBrush.Visual> </VisualBrush> </Setter.Value> </Setter> </DataTrigger> </Style.Triggers> 
8
29 апр. Cavab Edd 29 apr verilir . 2015-04-29 16:59 '15 'də saat 16:59' da

Hər bir cavab oxumamışdım, ancaq bu məlumatı düymənin mənbə kodunun nisbi bir şəkildə bağlanması halında əlavə etmək istərdim.

Mode=FindAncestor ilə nisbi bir mənbədən istifadə edərkən, cəlb belə olmalıdır:

 Command="{Binding Path=DataContext.CommandProperty, RelativeSource={...}}" 

Yolunuza DataContext əlavə etmirsinizsə, mülkü iş vaxtında ala bilmir.

8
29 июля '16 в 11:30 2016-07-29 11:30 Cavab Kevin VDF tərəfindən 29 İyul tarixində saat 16: 30-da 2016-07-29 11:30 tarixində verildi

Element vizual ağacın bir hissəsidirsə, RelativeSource işləməyəcəkdir.

Bu halda, əvvəlcə Tomas Leveskinin təklif etdiyi başqa bir texnikanı sınamalısınız.

Onun [WPF] bloqunda bir həll var DataContext miras alındıqda məlumatlara necə bağlanır . Və tamamilə parlaq işləyir!

Bloqunun aşağı olduğu ehtimalı olan halda Əlavə A məqalənin güzgü surətini ehtiva edir.

Xahiş edirik burada şərh etməyin, birbaşa blog yazısında şərh edin.

Əlavə A: Blog Post Mirror

WPF DataContext mülkiyyəti avtomatik olaraq təyin etdiyiniz elementin bütün uşaqları tərəfindən miras alındığı üçün son dərəcə rahatdır; buna bağlamaq istədiyiniz hər bir maddə üçün təkrar yükləməyin lazım deyil. Lakin, bəzi hallarda DataContext mövcud deyil: bu, görsel və ya ağıllı ağacın bir hissəsi olmayan maddələr üçün olur. Bir əmlakı bu elementlərə bağlamaq çox çətin ola bilər ...

Sadə nümunə ilə nümunə verək: DataGrid-də məhsulların siyahısını təqdim etmək istəyirik. Şəkildə, ViewModel tərəfindən açılan ShowPrice xüsusiyyətinin dəyərinə əsaslanan "Qiymət" sütunu göstərmək və ya gizlətmək istəyirik. Aşkar yanaşma, sütunun görünürlüğünü ShowPrice özelliğine bağlamaktır:

 <DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False" Visibility="{Binding ShowPrice, Converter={StaticResource visibilityConverter}}"/> 

Təəssüf ki, ShowPrice dəyərinin dəyişdirilməsi təsir etmir və sütun həmişə görünür ... niyə? Visual Studio'da çıxış pəncərəsinə baxdığımızda aşağıdakı xəttləri görürük:

System.Windows.Data səhv: 2: hədəf element üçün FrameworkElement nəzarət və ya FrameworkContentElement tapılmadı. BindingExpression: Path = ShowPrice; DataItem = NULL; hədəf element "DataGridTextColumn (HashCode = 32685253); hədəf" Görünürlük (növü "Görünürlük")

Mesaj olduqca sirli, amma nöqtə əslində olduqca sadədir: WPF, DataContext'i almaq üçün hansı FrameworkElement istifadə etməkini bilmir, çünki sütun əyani və mantıksız DataGrid ağacına aid deyil.

İstədiyiniz nəticəni əldə etmək üçün, məsələn, DataGrid-də RelativeSource-u tənzimləyərək, bağlamanı fərdiləşdirməyə çalışa bilərik:

 <DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False" Visibility="{Binding DataContext.ShowPrice, Converter={StaticResource visibilityConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/> 

Yoksa ShowPrice'e bir CheckBox bağlantısı əlavə edə və sütun görünürlüğünü IsChecked özelliğine elemanın adını belirlemeye çalışırıq:

 <DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False" Visibility="{Binding IsChecked, Converter={StaticResource visibilityConverter}, ElementName=chkShowPrice}"/> 

Amma bu əsərlərin heç biri işləmir, həmişə eyni nəticəni alırıq ...

Halbuki, göründüyü kimi, MVVM nümunəsini istifadə edərkən, qaçınmaq üçün üstünlük verən sütunun görünürlüğünü dəyişdirmək mümkündür ... Amma tezliklə imtina etməyəcəyəm, ən azı başqa variantları nəzərə almır

Problemimizin həlli əslində olduqca sadədir və Freezable sinfi istifadə edir. Bu sinifin əsas məqsədi obyektləri dəyişkən və oxunan bir dövlət ilə müəyyən etməkdir, lakin bizim işimizdə maraqlı bir xüsusiyyət, onlar bir Görsel və ya mantıksız ağacda olmasa belə, DataContext'i miras edə bilər. Mən bu davranışa imkan verən dəqiq mexanizmi bilmirəm, amma mən bunu istinad ilə işimizi etmək üçün istifadə edəcəyik ...

Ideyası Freezable devralır və məlumatların asılılıq əmlakını elan edən bir sinif yaratmaqdır (mən bunu BindingProxy adını çoxdan tezliklə aydınlaşdırmaq lazımdır)

 public class BindingProxy : Freezable { #region Overrides of Freezable protected override Freezable CreateInstanceCore() { return new BindingProxy(); } #endregion public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc... public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); } 

Daha sonra DataGrid resurslarında bu sinifin bir nümunəsini bəyan edə bilərik və Data əmlakını mövcud DataContext ilə birləşdirə bilərik:

 <DataGrid.Resources> <local:BindingProxy x:Key="proxy" Data="{Binding}" /> </DataGrid.Resources> 

Son addım bu BindingProxy obyektini (bir StaticResource ilə asanlıqla əlçatan) göstərmək üçün bağlama mənbəyi kimi göstərməkdir:

 <DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False" Visibility="{Binding Data.ShowPrice, Converter={StaticResource visibilityConverter}, Source={StaticResource proxy}}"/> 

Yolu indi BindingProxy obyektinə aid olduğundan, məcburi yolun Prefiks məlumatına malik olduğuna diqqət yetirin.

Binding indi düzgün işləyir və sütun ShowPrice xüsusiyyətinə əsasən düzgün görüntülenir və ya gizlənir.

3
05 сент. Cavab tərtib olunur. 2017-09-05 13:46 '17 saat 13:46 'də 2017-09-05 13:46

etiketləri haqqında suallar və ya bir sual