2013-03-19 14 views
6

nie jestem pewien, czy mój nagłówek pytanie reprezentują dokładnie mój problem, zrobię najlepiej wyjaśnić:Wiele DataContext dla jednej kontroli - MVVM

Mam DataTemplate komórek siatki (siatka należą do spółki przez osoby trzecie ale nie `s ważne dla mojego pytania

<DataTemplate> 
    <TextBlock> 
     <Hyperlink Command="{Binding OpenLinkCommand}"> 
      <Hyperlink.ToolTip> 
       <TextBlock Text="{Binding Data.MapLink}"/> 
      </Hyperlink.ToolTip> 
      <TextBlock Text="{Binding Data.MapLink}" TextDecorations="underline"> 
     </Hyperlink> 
    </TextBlock> 
</DataTemplate> 

chcę uczynić ten DataTemplate aby pokazać pewne hiperłącza („Data.MapLink”jest obiektem, który zawiera wartość linku) i każde kliknięcie na ten link pożaru) polecenie "OpenLinkCommand".

Problem polega na tym, że „Data.MapLink” i „OpenLinkCommand” znajdują się w różnych DataContext a następnie trzeba wybrać jedną z kolejnych wyborów:

  1. urlopu hiperłącze DataContext jak to - wygranego polecenia `t działa, a hiperłącze otrzyma wartość Data.MapLink.

  2. zmiana danych hiperłączaKoniec do polecenia datacontext - Polecenie będzie działać, ale nazwa hiperłącza będzie pusta.

żalem Nie znam mają możliwość umieścić te elementy w tej samej DataContext więc muszę znaleźć sposób, jak powiedzieć, że polecenie DataContext jest „X” i powiedzieć, że hiperłącze DataContext jest „Y”.

Mam nadzieję, że moje pytanie jest jasne. Jak mogę rozwiązać ten problem?

+1

Skąd pochodzi drugi datacontext? jest związany z elementem, ponieważ możesz powiązać element danych z innym elementem i ustawić względne źródło. Jeśli masz dostęp do obu formatów danych w swoim modelu widoku (zakładając, że używasz viewmodel), możesz pobrać drugie polecenie. – TYY

+0

użyj RelativeSource w bindowaniu, aby znaleźć właściwy datacontext – blindmeis

+0

Właśnie zgłosiłem błąd (innym razem?) Do Microsoft: https://connect.microsoft.com/VisualStudio/feedback/details/1398835/binding-of-readonly-dependencyproperty –

Odpowiedz

15

Istnieją pewne właściwości wiązania można użyć, aby określić inną Source na swój wiążący niż domyślny DataContext

najczęstsze z nich to ElementName lub RelativeSource, które znajdą inny element interfejsu użytkownika w VisualTree, dzięki czemu można powiązać jego właściwości.

Na przykład poniższa wykorzystuje ElementName powiedzieć wiązanie że powinien używać MyGridView jako źródło wiązania, a także wiązać się z MyGridView.DataContext.OpenLinkCommand

<Hyperlink Command="{Binding ElementName=MyGridView, 
          Path=DataContext.OpenLinkCommand}"> 

Można również użyć RelativeSource w wiążącym, aby znaleźć obiekt dalej up VisualTree określonego typu obiektu i użyj go jako źródła wiązania. Ten przykład robi to samo, co powyższy przykład, z tym wyjątkiem, że używa RelativeSource zamiast ElementName, więc Twój GridView nie musi mieć określonego Name.

<Hyperlink Command="{Binding 
       RelativeSource={RelativeSource AncestorType={x:Type GridView}}, 
       Path=DataContext.OpenLinkCommand}"> 

Trzecią opcją jest ustawienie wiązania na Source własności do obiektu statycznego, jak poniżej:

<Hyperlink Command="{Binding 
       Source={x:Static local:MyStaticClass.OpenLinkCommand}}"> 

podstawie your comment here o wiązanie z Singleton, to prawdopodobnie byłby najlepszym rozwiązaniem dla Ciebie .

+0

Witam, Twoje rozwiązanie wydaje się być tym, czego szukam. Spróbuję go dzisiaj i zgłoś, jeśli rozwiązał mój problem. – Ofir

+0

Twoje rozwiązanie działa doskonale !!! Dziękuję – Ofir

+0

@Ofir Cieszę się, że wypracowaliśmy dla ciebie :) – Rachel

0

Będziesz musiał mieć wystąpienie żądanego kontekstu danych (zwykle w zasobach kontrolki lub okna). Gdy już to zrobisz, powinieneś być w stanie jawnie ustawić kontekst danych bloku tekstowego zamiast dziedziczenia kontekstu danych nadrzędnych automatycznie.

Na przykład:

<TextBlock DataContext="{StaticResource MyDataMapLinkDataContext}" Text="{Binding Data.MapLink}" TextDecorations="underline"/> 
+1

Tak Myślałem o tej drodze, ale nie mogę utworzyć innego datacontext instace (Mój datacontext musi być singleTon). Jakieś inne sugestie? – Ofir

+0

Możesz powiązać swoje hiperłącze z kontekstem danych macierzystych za pomocą metody findativesource. Dokładny kod wiążący zależy od tego, jak masz strukturę XAML. Może opublikuj swoje xaml, jeśli potrzebujesz pomocy w tym. – failedprogramming

+0

Powiedziałeś również, że nie możesz umieścić obu poleceń w tym samym pliku danych, jeśli używasz mvvm, możesz objąć oba modele widoków w trzeci i wyświetlić oba polecenia. – failedprogramming

0

Jeśli naprawdę trzeba używać innego lokalu za dodatkową kontekstu danych to możesz po prostu użyć załączony właściwość.

XAML

<Window.Resources> 
     <Style TargetType="Button"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="Button"> 
         <ContentPresenter Content="{Binding (local:ExtraDataContextProvider.ExtraDataContext), RelativeSource={RelativeSource TemplatedParent}}"/> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 

    <Grid> 
     <Button Margin="172,122,131,79" Foreground="Green" local:ExtraDataContextProvider.ExtraDataContext="A test"> 
      test 
     </Button> 
    </Grid> 
</Window> 

Kod

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace WpfApplication1 
{ 

    public class ExtraDataContextProvider : DependencyObject 
    { 
     public static object GetExtraDataContext(DependencyObject obj) 
     { 
      return (object)obj.GetValue(ExtraDataContextProperty); 
     } 

     public static void SetExtraDataContext(DependencyObject obj, object value) 
     { 
      obj.SetValue(ExtraDataContextProperty, value); 
     } 

     public static readonly DependencyProperty ExtraDataContextProperty = DependencyProperty.RegisterAttached("ExtraDataContext", typeof(object), typeof(ExtraDataContextProvider), new PropertyMetadata(null)); 
    } 

    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 
    } 
} 
Powiązane problemy