5

Это код XAML, что я используюПередача дополнительных аргументов для пользовательского элемента управления внутри шаблона данных

<GridView 
     Grid.Row="0" 
     x:Name="RootGrid" 
     SelectionMode="None" 
     IsItemClickEnabled="True" 
     ItemsSource="{Binding RootListSource}"> 

     <GridView.ItemTemplate> 
      <DataTemplate> 
       <UserControl:TreeInfoControl/> 
      </DataTemplate> 
     </GridView.ItemTemplate> 

    </GridView> 

В этом моем контроле пользователя, он содержит еще один GridView, который содержит различное IEnumerable коллекции. То, что я пытаюсь достичь, мне нужно передать эту коллекцию с помощью кода. Я попробовал это, добавив свойство зависимостей в treecontrol, но он не работает. Поэтому я ищу решение, которое позволяет передавать коллекцию через xaml (каким-то образом через пользовательский элемент управления). Я знаю, что можно добавить эту коллекцию в существующую коллекцию и связать ее. Но пока я не могу использовать этот метод.

+3

Я также ищу решение этой проблемы. В WPF возможно –

+0

Слишком плохо, что вы не можете использовать технику, которая работает. –

ответ

6

Вот как вы это делаете.

Начать с App.xaml так мы можем использовать демонстрационный шаблон

<Application.Resources> 
    <DataTemplate x:Key="MyContentControl"> 
     <Grid Height="100" Width="100" Background="Maroon"> 
      <TextBlock Text="{Binding FallbackValue=0}" Foreground="White" FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center" /> 
     </Grid> 
    </DataTemplate> 
</Application.Resources> 

Тогда мы можем определить ваш пользовательский элемент управления

<d:UserControl.DataContext> 
    <local:MyControlViewModel Number="-1" Letter="~K" /> 
</d:UserControl.DataContext> 

<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left"> 
    <ContentControl Content="{Binding Number}" 
        ContentTemplate="{StaticResource MyContentControl}" /> 
    <ListView ItemsSource="{Binding Letters}" IsHitTestVisible="False" 
       ItemTemplate="{StaticResource MyContentControl}" 
       SelectedItem="{Binding Letter, Mode=TwoWay}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <ItemsStackPanel Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ListView> 
</StackPanel> 

И тогда мы можем определить ваш MainPage.xaml

<Page.DataContext> 
    <local:MainPageViewModel Letter="C" /> 
</Page.DataContext> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="140" /> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <ListView x:Name="MyList" ItemsSource="{Binding Letters}" 
       ItemTemplate="{StaticResource MyContentControl}" 
       SelectedItem="{Binding Letter, Mode=TwoWay}" /> 
    <ListView Grid.Column="1" ItemsSource="{Binding Numbers}"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <StackPanel.Resources> 
         <local:MyControlViewModel 
          x:Key="MyDataContext" Number="{Binding}" 
          Letters="{Binding ItemsSource, ElementName=MyList}" 
          Letter="{Binding SelectedItem, ElementName=MyList}" /> 
        </StackPanel.Resources> 
        <local:MyControl DataContext="{StaticResource MyDataContext}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
</Grid> 

Ничего особенного, не так ли? Ну, не так быстро. Мы создаем viewmodel для пользовательского элемента управления, устанавливаем свойства модели представления из окружающего пространства, а затем явно передаем его в DataContext пользовательского элемента управления. Круто, да? Достаточно просто, если вы думаете об этом. Хотите установить эти свойства внутри тега? Конечно. Но вы не можете. Порядок действий будет неправильным. Тебе просто нужно доверять мне.

Теперь для вашего пользовательского контроля есть код ZERO. Но модель вида выглядит так:

public class MyControlViewModel : BindableBase 
{ 
    public int Number 
    { 
     get { return (int)GetValue(NumberProperty); } 
     set 
     { 
      SetValue(NumberProperty, value); 
      base.RaisePropertyChanged(); 
     } 
    } 
    public static readonly DependencyProperty NumberProperty = 
     DependencyProperty.Register("Number", typeof(int), typeof(MyControlViewModel), 
     new PropertyMetadata(0, (s, e) => { })); 

    public string Letter 
    { 
     get { return (string)GetValue(LetterProperty); } 
     set 
     { 
      SetValue(LetterProperty, value); 
      base.RaisePropertyChanged(); 
     } 
    } 
    public static readonly DependencyProperty LetterProperty = 
     DependencyProperty.Register("Letter", typeof(string), typeof(MyControlViewModel), 
     new PropertyMetadata("Z", (s, e) => { })); 

    public ObservableCollection<string> Letters 
    { 
     get { return (ObservableCollection<string>)GetValue(LettersProperty); } 
     set 
     { 
      SetValue(LettersProperty, value); 
      base.RaisePropertyChanged(); 
     } 
    } 
    public static readonly DependencyProperty LettersProperty = 
     DependencyProperty.Register("Letters", typeof(ObservableCollection<string>), 
     typeof(MyControlViewModel), 
     new PropertyMetadata(new ObservableCollection<string>(new[] { "~W", "~X", "~Y", "~Z" }), (s, e) => { })); 
} 

Все свойства являются зависимыми свойствами. Надеюсь, вы заметили. Я просто не делал этого, потому что мне нравилось печатать. Хотя я действительно люблю печатать. Факт, я сделал это, потому что для того, чтобы иметь внутреннюю привязку, вы должны использовать свойство зависимости - и свойство зависимостей, которое повышает свойство, изменилось! Эта последняя часть не является тривиальной. Но нужно ли это быть в модели представления? Нет. Но мне это нравится.

Вы можете ссылаться на это: http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html

Там также нет кода позади вашего MainPage. Но вид модель выглядит следующим образом:

public class MainPageViewModel : BindableBase 
{ 
    public MainPageViewModel() 
    { 
     this._Letters = new ObservableCollection<string>(new[] { "A", "B", "C", "D" }); 
     this._Numbers = new ObservableCollection<int>(new[] { 1, 2, 3, 4 }); 
    } 

    public string Letter 
    { 
     get { return (string)GetValue(LetterProperty); } 
     set 
     { 
      SetValue(LetterProperty, value); 
      base.RaisePropertyChanged(); 
     } 
    } 
    public static readonly DependencyProperty LetterProperty = 
     DependencyProperty.Register("Letter", typeof(string), typeof(MyControlViewModel), 
     new PropertyMetadata("Z", (s, e) => { })); 

    ObservableCollection<string> _Letters = new ObservableCollection<string>(); 
    public ObservableCollection<string> Letters { get { return _Letters; } } 

    ObservableCollection<int> _Numbers = new ObservableCollection<int>(); 
    public ObservableCollection<int> Numbers { get { return _Numbers; } } 
} 

Привязываемой база стандартна, вот код для этого:

public abstract class BindableBase : DependencyObject, System.ComponentModel.INotifyPropertyChanged 
{ 

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 
    protected void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null) 
    { 
     if (!object.Equals(storage, value)) 
     { 
      storage = value; 
      if (PropertyChanged != null) 
       PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    protected void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = null) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); 
    } 
} 

Когда все это сделано, вы должны получить именно то, что вы хотите. Что-то вроде этого:

enter image description here

Не упрощать вещи. Но это так просто.

Посмотрите, что ваша голова, обернутая вокруг XAML, не всегда легка, когда вы начинаете посещать контексты. Я не обвиняю вас в том, что вы не получили его в первый раз. Но я надеюсь, что это поможет вам начать работу.Продолжайте толкать

Удачи!

+0

Спасибо Никсон. Это мне очень помогло. Спасибо за ваш совет.. :) – StezPet

Смежные вопросы