C#WPF:拖动列表框以选择文本

时间:2015-07-02 14:13:59

标签: c# .net wpf xaml listbox

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

内容转换器绑定:
需要将ListBox中的项目传递给将项目转换为文本格式的转换器。

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

我实现了[此复制/粘贴解决方案] [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项目中选择文字?

感谢您的帮助,
查理

修改

这是转换器代码......

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}}"/>

2 个答案:

答案 0 :(得分:1)

试试这个。 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>  

答案 1 :(得分:1)

你试过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;
    }
}