我看到多年来一直有很多问题,关于如何最好地与数据模板中的数据绑定,是否有最佳实践?在这种情况下,我希望我的MemoryCopyBtn复制当前所选MemoryListItem TextBox的文本,以便我可以在ViewModel中对它进行处理。
我可以使用Findname找到ListView,但它会在PageLoad上为ListViewItem显示null。
我可以将所有内容都放在内存模型页面中,但我不认为这是最佳做法。
我看到这是走遍可视代码树的各种选项,但我想在运行时这样做,这真的是唯一的方法吗?
我有什么选择? 谢谢。
<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 :(得分: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);
}
}
答案 1 :(得分:1)
我认为您可以在MemoryItem
中绑定Button的Click事件,然后您可以获取此事件中单击按钮的数据上下文。
为了测试,我在这里写了一个非常简单的演示:
<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 Helper来完成这项工作,x:Bind可以用于事件,它在这里非常有用。
答案 2 :(得分:0)
如果你想纯粹使用x:Bind,我建议你在XAML中定义Click事件,Click="onButtonClicked"
。在View中,您调用ViewModel(在MVVM中,View知道VM)或者您可以发布消息,ViewModel将捕获它并执行工作。 MVVM Light有这种Messenger机制。