0

我看到多年来有很多问题被问到,关于如何最好地与数据模板中的数据绑定,是否有最佳实践?在这种情况下,我希望我的 MemoryCopyBtn 复制当前选定的 MemoryListItem 文本框的文本,以便我可以在 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>
4

3 回答 3

1

我认为您可以在 Button 中绑定 Click 事件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 Helper 来完成这项工作,x:Bind 可以用于事件,它在这里非常有用。

于 2016-04-22T06:49:19.487 回答
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);
    }
}
于 2016-04-22T05:58:59.053 回答
0

如果你想纯粹使用 x:Bind,我建议你在 XAML 中定义 Click 事件,Click="onButtonClicked". 在 View 中,您调用 ViewModel(在 MVVM 中,View 知道 VM)或者您可以发布消息,ViewModel 将捕获它并完成工作。MVVM Light 具有这种 Messenger 机制。

于 2016-04-21T21:01:38.967 回答