2016-04-21 2 views
0

Я вижу, что на протяжении многих лет был задан много вопросов, о том, как лучше всего привязываться к данным в рамках набора данных, есть ли лучшая практика? В этом случае я хочу, чтобы мой MemoryCopyBtn скопировал текст выбранного в данный момент TextLox MemoryListItem, чтобы я мог работать с ним в ViewModel.Лучшая практика связывания свойств элементов управления в DataTemplate?

Я могу найти ListView с помощью Findname, но он покажет null для ListViewItem на странице Load.

Я могу разместить все на странице модели памяти, но я не думаю, что это лучшая практика.

Я вижу, что это разные варианты для того, чтобы ходить по визуальному коду кода, но я хочу сделать это во время выполнения, это действительно единственный способ?

Какие у меня варианты? Спасибо.

<ListView x:Name="ClipboardList" 
         xmlns:m="using:QuickieEdit.Models" 
         ItemsSource="{x:Bind ViewModel.MemoryItems}"> 
       <ListView.ItemTemplate> 
        <DataTemplate x:DataType="m:MemoryItem"> 
          <StackPanel Orientation="Horizontal"> 
           <Button x:Name="MemoryCopyBtn" 
              Content="Copy" 
              Click="How to Copy currently selected 
              MemoryListItem.Text?"/> 
           <TextBox x:Name="MemoryListItem" 
               Text="{x:Bind Memory, Mode=TwoWay}"> 
           </TextBox>         
          </StackPanel> 
        </DataTemplate> 
       </ListView.ItemTemplate> 
</ListView> 
+0

Нажав на кнопку, вы хотите скопировать текст в TextBox, который находится в том же DataTemplate? – Evk

+0

Да. Я хочу скопировать текущий выбранный или сфокусированный TextBox.Content ListViewItem. –

ответ

1

Если вы правильно поняли - вы хотите скопировать текст текстового поля, который находится вместе с кнопкой, которую вы нажимаете, а не выбранным \ сфокусированным текстовым полем (в противном случае это не имеет смысла, поскольку у вас есть кнопка копирования для каждого элемента в вашем списке). Если это так, просто используйте команду:

<ListView.ItemTemplate> 
     <DataTemplate x:DataType="m:MemoryItem"> 
      <StackPanel Orientation="Horizontal"> 
       <Button x:Name="MemoryCopyBtn" 
         Content="Copy" 
         Command="{Binding CopyCommand}" 
         CommandParameter="{Binding ElementName=MemoryListItem, Path=Text}" /> 
       <TextBox x:Name="MemoryListItem" 
         Text="{x:Bind Memory, Mode=TwoWay}"></TextBox> 
      </StackPanel> 
     </DataTemplate> 
    </ListView.ItemTemplate> 

И в вашем MemoryItem:

public class MemoryItem { 
    public MemoryItem() { 
     CopyCommand = new RelayCommand(Copy); 
    }   

    public string Memory { get; set; } 
    public ICommand CopyCommand { get; private set; } 

    private void Copy(object argument) 
    { 
     var text = (string)argument; 
     Console.WriteLine(text); 
    } 
} 
+0

Это означает, что вы создаете экземпляр 'RelayCommand' для каждого элемента в списке. Нет лучшего решения с точки зрения масштабируемости. – DHN

+0

@DHN Экземпляр ICommand для каждого элемента будет иметь абсолютно нулевой эффект на масштабируемость и производительность. – Evk

+0

Интересно, что вы потребляете память с каждым экземпляром, не так ли? – DHN

0

Если вы хотите использовать чисто х: Bind, я предлагаю вам определить Click событие в XAML, Click="onButtonClicked". В представлении вы вызываете ViewModel (в MVVM, представление знает виртуальную машину), или вы можете опубликовать сообщение, ViewModel поймает его и выполнит работу. MVVM Light имеет этот механизм Messenger.

+0

Я вызываю ли ListViewItem в ViewModel с помощью FindName или в коде View позади с SelectionChanged или в самом текстовом поле с GetFocus, ListviewItem.Content всегда возвращается к нулю. Я предполагаю, что то, что я ищу, является наилучшей практикой для возврата выбранного или сфокусированного содержимого ListViewItem. –

+0

По содержанию вы имеете в виду объект, привязанный к элементу списка или содержимому xaml в элементе списка?Если вы хотите получить доступ к объекту, вы можете получить его из «DataContext» объекта-отправителя в обработчике событий. Вы также можете использовать x: Bind для привязки к обработчику событий в ViewModel, поэтому вам больше не нужно обрабатывать событие в представлении. – thang2410199

1

Я думаю, что вы можете связать событие нажатия кнопки в вашем MemoryItem, то вы можете получить контекст данных из клики в этом случае.

Только для теста я написал очень простой демо здесь: за

<ListView x:Name="ClipboardList" ItemsSource="{x:Bind ViewModel.MemoryItems}"> 
    <ListView.ItemTemplate> 
     <DataTemplate x:DataType="local:MemoryItem"> 
      <StackPanel Orientation="Horizontal"> 
       <Button x:Name="MemoryCopyBtn" 
            Content="Copy" 
            Click="{x:Bind MemoryCopyBtn_Click}" /> 
       <TextBox x:Name="MemoryListItem" 
             Text="{x:Bind Memory, Mode=TwoWay}"> 
       </TextBox> 
      </StackPanel> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

Код:

private MainPageViewModel ViewModel; 

public MainPage() 
{ 
    this.InitializeComponent(); 
    ViewModel = new MainPageViewModel(); 
} 

Мой MainPageViewModel класс:

public class MainPageViewModel 
{ 
    public ObservableCollection<MemoryItem> MemoryItems; 

    public MainPageViewModel() 
    { 
     MemoryItems = new ObservableCollection<MemoryItem>(); 
     MemoryItems.Clear(); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 1" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 2" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 3" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 4" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 5" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 6" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 7" }); 
     MemoryItems.Add(new MemoryItem { Memory = "Item 8" }); 
    } 
} 

Класс MemoryItem:

public class MemoryItem 
{ 
    public string Memory { get; set; } 

    public void MemoryCopyBtn_Click(object sender, RoutedEventArgs e) 
    { 
     var item = ((FrameworkElement)e.OriginalSource).DataContext as MemoryItem; 
     var text = item.Memory; 
    } 
} 

Этот код здесь не на 100% такой же, как ваш, очень простой для тестирования, пожалуйста, не возражайте. В обычных случаях мы избегаем использования помощника VisualTree для выполнения этой работы, x: Bind может использоваться для события, это очень полезно здесь.

+0

Спасибо, Грейс Фэн. Я решил пойти с подходом Evk's Command ниже, главным образом потому, что я хотел использовать Command, но я ценю вашу помощь! –

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