Soru RelativeSource ile WPF bağlarını nasıl kullanırım?


Nasıl kullanırım RelativeSource WPF bağlamaları ve farklı kullanım durumları nelerdir?


521
2017-09-17 15:10


Menşei




Cevaplar:


Nesnede başka bir özelliğe bağlamak isterseniz:

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

Bir ataya ait bir mülk almak istiyorsan:

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

Templated ebeveyne bir özellik almak istiyorsanız (böylece bir ControlTemplate'de 2 yollu bağlamalar yapabilirsiniz)

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

veya daha kısa (bu yalnızca OneWay bağlamaları için çalışır):

{TemplateBinding Path=PathToProperty}

697
2017-09-17 15:14



Bunun için "{Binding Path = PathToProperty, RelativeSource = {RelativeSource AncestorType = {x: Type typeOfAncestor}}}", "AncestorType" önce "Mode = FindAncestor" olması gerekiyor gibi görünüyor - EdwardM
Hangi teknoloji için? WPF'de, bir AncestorType. - Abe Heidebrecht
@EdwardM ile aynı fikirdeyim. İhmal ettiğimde FindAncestor, önce AncestorTypeAşağıdaki hatayı alıyorum: "RelativeSource FindAncestor modunda değil". (VS2013, Topluluk sürümünde) - kmote
Kmote, bu benim için çalıştı. Net 3.0, ve bir kez daha kaxaml'da bu şekilde çalıştığını doğruladım ... Yine, hangi teknolojiyi kullanıyorsunuz? XAML işlemci WPF / Silverlight / UWP için farklıdır, dolayısıyla farklı teknolojiler üzerinde farklı sonuçlar elde edebilirsiniz. Ayrıca VS Topluluğu'ndan da bahsettiniz, bu yüzden bir IDE uyarısıdır, ancak çalışma zamanında mı çalışıyor? - Abe Heidebrecht
VS Community 2018'de yeniden oluşturma, bu hataları (ve bunun gibi) ortadan kaldırır. - will-hart


Binding RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...

Varsayılan özellik RelativeSource öyle mi Mode özelliği. Tam bir geçerli değerler kümesi burada verilmiştir (MSDN'den):

  • PreviousData Görüntülenmekte olan veri öğeleri listesinde önceki veri öğesini (veri öğesini içeren kontrol değil) bağlamanıza izin verir.

  • TemplatedParent Şablonun (veriye bağlı elemanın var olduğu) uygulandığı öğeyi ifade eder. Bu, bir TemplateBindingExtension ayarlamaya benzer ve yalnızca Bağlama bir şablon içinde ise uygulanabilir.

  • öz Bağlamayı ayarladığınız öğeyi belirtir ve bu öğenin bir özelliğini aynı öğe üzerindeki başka bir özelliğe bağlamanızı sağlar.

  • FindAncestor Veriye bağlı öğenin üst zincirindeki ataya karşılık gelir. Bunu, belirli bir türün veya alt sınıflarının atalarına bağlamak için kullanabilirsiniz. AncestorType ve / veya AncestorLevel belirtmek istiyorsanız, kullandığınız moddur.


122
2018-03-03 09:24





İşte MVVM mimarisi bağlamında daha görsel bir açıklama:

enter image description here


113
2018-03-16 02:35



RelativeSource hakkında çok şey okuyun ama bu küçük grafik gibi bir şeyi BASİT ve CLEAR olarak görmediniz! Teşekkürler, teşekkürler, teşekkürler. - Sylvain Rodrigue
Bir şey mi kaçırdım? Bunu basit ve net bir grafik olarak nasıl değerlendirirsiniz? 1: Soldaki anlamdaki kutular gerçekten sağdakiler ile ilgili değildir (neden ViewModel içinde bir .cs dosyası var?) 2: Bu DataContext okları neye işaret ediyor? 3: Message özelliği neden ViewModel1'de değil? ve en önemlisi 5: TextBlock'un aynı DataContext'e sahip olması durumunda, Window'ın DataContext'ine ulaşmak için neden bir RelativeSource Bağlayıcısı'na ihtiyacınız var? Burada açıkça bir şeyi özlüyorum, ya çok aptalım ya da bu grafik herkesin düşündüğü kadar basit ve net değil! Lütfen beni aydınlat - Markus Hütter
@ MarkusHütter Şema bir gruba iç içe geçmiş Görünümler ve ilgili ViewModels'i gösteriyor. View1'in DataContext'i ViewModel1'dir, ancak BaseViewModel'in bir özelliğine bağlamak ister. BaseViewModel BaseView DataContext (bir pencere) olduğu için, bir pencere olan ve DataContext alarak ilk ana kapsayıcıyı bularak bunu yapabilir. - mcargille
@MatthewCargille Ne olduğunu çok iyi biliyorum sözdedemek istediğim, bu benim amacım değildi. Ama kendinizi XAML ve MVVM'yi iyi bilmeyen birinin konumuna koyun ve bunun olmadığını göreceksiniz. basit ve açık. - Markus Hütter
Bu arada, @ MarkusHütter ile aynı fikirdeyim, bu arada soldaki bağlanma şu kadar basit olabilir: {Binding Message} (biraz daha basit ...) - florien


Bu durumu düşünün, dikdörtgenin her zaman genişliğine eşit olmasını istediğimiz bir dikdörtgen, bir kare diyelim. Bunu eleman ismini kullanarak yapabiliriz

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

Ancak bu durumda, bağlayıcı nesnenin adını, yani dikdörtgeni belirtmek zorundayız. RelativeSource kullanarak aynı amaca ulaşabiliriz

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

Bu durumda, bağlama nesnesinin adını belirtmek zorunda değiliz ve yükseklik değiştiğinde Genişlik her zaman Yüksekliğe eşit olacaktır.

Genişliği, yüksekliğin yarısı olacak şekilde parametrelemek isterseniz, bunu Binding işaretleme uzantısına bir dönüştürücü ekleyerek yapabilirsiniz. Şimdi başka bir vaka düşünelim:

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

Yukarıdaki durum, belirli bir öğenin belirli bir özelliğini, ana öğe olarak adlandırılan bir özelliğe sahip olduğu için doğrudan ana öğelerinden birine bağlamak için kullanılır. Bu bizi FindAncestor olan başka bir göreli kaynak moduna götürür.


40
2017-11-09 05:47



Kopyalayıp yapıştırdığınızda kaynağınızdan alıntı yapmak en iyisidir. - Jeremy
@Jeremy için atıfta bulunuyor bu eğitim tarafından 11 Mayıs 2010'dan Bechir Bejaoui. - Zach Mierzejewski
@ZachMierzejewski Teşekkürler, SO cevabı paragraf gibi okur ve örnekler eksiktir. - Ryan The Leach


Bechir Bejaoui, WFP'de RelativeSources kullanım durumlarını açıklar. onun makalesi:

RelativeSource, özellikle kullanılan bir işaretleme uzantısıdır   Belirli bir nesnenin özelliğine bağlanmaya çalıştığımızda   Bir özelliği bağlama girişiminde bulunduğumuzda, nesnenin kendisinin bir başka özelliği   bir nesneyi, bir   özel denetim durumunda bağımlılık özellik değeri bir XAML parçasına   bir dizi diferansiyelin kullanılması durumunda gelişme ve son olarak   bağlı bir veri. Bütün bu durumlar göreli kaynak olarak ifade edilir.   modları. Tüm bu vakaları tek tek açığa çıkaracağım.

  1. Mod öz:

Bu vakayı düşünelim, boyunun her zaman olmasını istediğimiz bir dikdörtgen   genişliğine eşit, bir kare diyelim. Bunu kullanarak yapabiliriz   eleman adı

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

Ancak bu durumda, isminin adını belirtmek zorundayız.   bağlayıcı nesne, yani dikdörtgen. Aynı amaca ulaşabiliriz   RelativeSource kullanarak farklı

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

Bu durumda bağlamanın adını belirtmek zorunda değiliz   Nesne ve Genişlik her zaman her zaman Yüksekliğe eşit olacaktır   yükseklik değiştirildi.

Genişliği boyunun yarısı olacak şekilde parametrelemek istiyorsanız   Binding markup uzantısına bir dönüştürücü ekleyerek bunu yapabilirsiniz.   Şimdi başka bir vaka düşünelim:

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

Yukarıdaki durum, belirli bir öğenin belirli bir özelliğini bağlamak için kullanılır.   Bu öğe olarak doğrudan ebeveynlerinden biri olan bir özellik taşır   Ebeveyn denir. Bu bizi başka bir akraba kaynağına götürür.   FindAncestor biri.

  1. Mod FindAncestor

Bu durumda, belirli bir elemanın mülkiyeti bir tanesine bağlanır.   Anne, Of Corse. Yukarıdaki durum ile ana fark aslında   Bu, ataların türünü ve atalarını belirlemek size kalmıştır   Özelliği hiyerarşide sıralamak. Bu arada oynamak için deneyin   bu XAML parçası

<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>

Yukarıdaki durum, gömülü olan iki TextBlock öğesinden oluşur.   bir dizi sınır ve tuval öğeleri içinde onların   hiyerarşik ebeveynler. İkinci TextBlock,   Göreli kaynak seviyesinde verilen ebeveyn.

Yani AncestorLevel = 2 değerini AncestorLevel = 1 olarak değiştirmeye çalışın ve neyin olduğunu görün.   olur. Sonra atadan türünü değiştirmeye çalışın.   AncestorType = AncestorType = Canvas ile sınırlayın ve neler olduğunu görün.

Görüntülenen metin Ancestor tipine göre değişecektir ve   seviyesi. O zaman atası seviyesine uygun değilse ne olur?   atası türü? Bu iyi bir soru, biliyorum ki   onu sor. Yanıt, istisnalar oluşturmayacak ve hiçbir şey yapılmayacak   TextBlock seviyesinde görüntülenmelidir.

  1. TemplatedParent

Bu mod belirli bir ControlTemplate özelliğini bir özelliğe bağlamayı sağlar   ControlTemplate'in uygulandığı denetimin. İyi   Buradaki sorunu anlamak bir örnek

<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>

Belirli bir kontrolün özelliklerini kendi kontrolüne uygulamak istiyorsam   şablonu daha sonra TemplatedParent modunu kullanabilirim. Ayrıca bir   TemplateBinding olan bu biçimlendirme uzantısına benzer   Birincisi kısa bir el, ama   TemplateBinding, derleme zamanında değerlendirilir.   İlk çalışma süresinden hemen sonra değerlendirilen TemplatedParent. Gibi   feryat figürü, arka plan ve içerikte dikkat çekebilirsiniz   Düğme içinden kontrol şablonuna uygulanır.


34
2017-10-19 20:34





TemplatedParent'i unutma:

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

veya

{Binding RelativeSource={RelativeSource TemplatedParent}}

17
2017-09-17 15:14





WPF'de RelativeSource bağlama üç ortaya çıkarır properties kurmak:

1. Mod: Bu bir enum Bu dört değerlere sahip olabilir:

a. PreviousData (value=0): Önceki değerine atar property için   bağlı olan

b. TemplatedParent (value=1):  Bu tanımlarken kullanılır templates arasında   herhangi bir kontrol ve bir değere bağlamak istiyorum / Mülkiyet control.

Örneğin, tanımlamak ControlTemplate:

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

c. Öz (value=2): Birinden bağlamak istediğimizde self ya da property Kendinin.

Örneğin: Kontrol edilen durumunu gönder checkbox gibi CommandParameter ayarlarken Command üzerinde CheckBox

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

d. FindAncestor (value=3): Bir ebeveynden bağlanmak istediğinizde control   içinde Visual Tree.

Örneğin: Bağlayın checkbox içinde records Eğer bir grid,Eğer header  checkbox kontrol edildi

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

2. AncesType:  mod ne zaman FindAncestor sonra ne tür ataları tanımlar

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

3. AncesLevel:  mod ne zaman FindAncestor o zaman hangi atasözü seviyesi (eğer aynı tür ebeveynler varsa visual tree)

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

Yukarıda tüm kullanım durumları RelativeSource binding.

İşte bir referans bağlantısı.


14
2018-01-21 13:41