C#WPF:列表框,通过拖动来选择文本

本文关键字:拖动 选择 文本 列表 C#WPF | 更新日期: 2023-09-27 18:00:57

我需要创建一个支持两个功能的WPF ListBox:

内容转换器绑定:
ListBox中的项需要传递给一个转换器,该转换器将这些项转换为文本格式。

以允许用户从ListBox项目中选择和复制文本的方式显示项目
我需要每个ListBox项目的文本都是可选的。用户希望使用鼠标拖动来选择部分元素,以便将文本复制到剪贴板。

我实现了[this复制/粘贴解决方案][1],但它不允许用户选择ListBox项文本的一部分,而是支持复制整个文本。

我可以使用转换器创建一个ListBox,但我不知道如何将转换后的文本放入一个控件中,让用户选择显示的文本。这是我所拥有的:

<ListBox Name="FinishedTestErrorsListBox"
         FontSize="12"
         ItemsSource="{Binding Path=SelectedComparisonResult.TestFailItems}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding Converter={StaticResource testFailItemConverter}}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>  

我已经尝试将TextBox添加到DataTemplate中,如下所示。。。

<TextBlock Text="{Binding Converter={StaticResource testFailItemConverter}}"/>  

但这会产生运行时错误,这是由于向转换器发送了错误类型的对象而导致的。我知道我在这里没有正确设置转换器绑定,尽管我没有很好地理解我应该如何在这里设置绑定,或者为什么这会导致错误。

所以,我的问题是:

我可以使用什么内容容器让用户从各个ListBox项目中选择文本

感谢您的帮助,
Charlie

编辑

这是转换器代码。。。

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
     ITestFailItem i = (ITestFailItem)value;
     return i.Itemize();
}  

编辑2

当ListBox首次初始化时,会引发以下运行时错误:

An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll 
Additional information: Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception

编辑3

罪魁祸首是我从原始代码片段中省略的一行代码,因为我认为它无关紧要——一路上我学到了很好的教训!

扩展问题

为什么以下代码段会导致错误?如何实现使文本框跨越整个包含网格的预期效果?

<TextBox Width="*"
         Text="{Binding Path=., Converter={StaticResource testFailItemConverter}}"/>

C#WPF:列表框,通过拖动来选择文本

试试这个。TextBlocks不支持文本选择,但TextBoxes支持。你只需要将其设为只读,这样用户就不能修改文本,并更改其边框厚度和背景,使其看起来像标签:

<ListBox Name="FinishedTestErrorsListBox"
         FontSize="12"
         ItemsSource="{Binding Path=SelectedComparisonResult.TestFailItems}">
    <ListBox.Resources>
        <converter:TestFailItemConverter x:Key="testFailItemConverter" />
    </ListBox.Resources>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Path=.,
                                    Converter={StaticResource testFailItemConverter},
                                    Mode=OneWay}"
                     BorderThickness="0"
                     Background="Transparent"
                     IsReadOnly="True"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>  

您尝试过TextBox吗?您可以在文本框中选择文本。路径必须更改为Path=.

<TextBox Text="{Binding Path=., Converter={StaticResource testFailItemConverter}}" />

没有太多代码可供使用,但这段代码对我有效:

xaml:

<Window x:Class="StackOverflowTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:s="clr-namespace:StackOverflowTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <s:TestFailItemConverter x:Key="testFailItemConverter" />
    </Window.Resources>
    <Grid>
        <ListBox Name="FinishedTestErrorsListBox"
         FontSize="12"
         ItemsSource="{Binding Path=SelectedComparisonResult.TestFailItems}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <!--<ContentControl Content="{Binding Converter={StaticResource testFailItemConverter}}"/>-->
                    <TextBox Text="{Binding Path=., Converter={StaticResource testFailItemConverter}}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

型号代码:

public class Dummy
    {
        public ObservableCollection<string> TestFailItems { get; set; }
        public Dummy()
        {
            TestFailItems = new ObservableCollection<string>(new List<string> { "a", "b" });
        }
    }
    public class Model
    {
        public Dummy SelectedComparisonResult { get; set; }
        public Model()
        {
            SelectedComparisonResult = new Dummy();
        }
    }

转换器代码:

public class TestFailItemConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return "aa";
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }
}