C# WPF:拖拽到 select 文本的列表框
C# WPF: Listbox with drag to select text
我需要创建一个支持两个功能的 WPF 列表框:
内容转换器绑定:
ListBox 中的项目需要传递给将项目转换为文本格式的转换器。
以允许用户 select 和从 ListBox 项目复制文本的方式显示项目
我需要每个 ListBox 项目的文本 selectable。用户希望使用鼠标拖动到元素的 select 部分,以便将文本复制到剪贴板。
我实施了 [这个 copy/paste 解决方案][1],但它不允许用户 select 列表框项目文本的一部分,而是支持复制整个文本。
我可以使用转换器创建一个列表框,但我不知道如何将转换后的文本放入一个控件中,让用户 select 显示文本。这是我拥有的:
<ListBox Name="FinishedTestErrorsListBox"
FontSize="12"
ItemsSource="{Binding Path=SelectedComparisonResult.TestFailItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Converter={StaticResource testFailItemConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我试过向 DataTemplate 添加一个 TextBox,如下所示...
<TextBlock Text="{Binding Converter={StaticResource testFailItemConverter}}"/>
... 但这会产生一个运行时错误,这是由于向转换器发送了错误类型的对象而引起的。我知道这里我没有正确设置转换器绑定,但我不太了解我应该如何在这里设置绑定或者为什么这会导致错误。
那么,我的问题是:
我可以使用什么内容容器让用户 select 来自各个 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}}"/>
试试这个。 TextBlock 不支持文本选择,但 TextBox 支持。您只需将其设置为只读,这样用户就无法修改文本,并更改其边框粗细和背景,使其看起来像标签:
<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吗?您可以 select 文本框内的文本。路径必须更改为 Path=.
<TextBox Text="{Binding Path=., Converter={StaticResource testFailItemConverter}}" />
没有多少代码可以使用,但这段代码对我有用:
xaml:
<Window x:Class="WhosebugTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:WhosebugTest"
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;
}
}
我需要创建一个支持两个功能的 WPF 列表框:
内容转换器绑定:
ListBox 中的项目需要传递给将项目转换为文本格式的转换器。
以允许用户 select 和从 ListBox 项目复制文本的方式显示项目
我需要每个 ListBox 项目的文本 selectable。用户希望使用鼠标拖动到元素的 select 部分,以便将文本复制到剪贴板。
我实施了 [这个 copy/paste 解决方案][1],但它不允许用户 select 列表框项目文本的一部分,而是支持复制整个文本。
我可以使用转换器创建一个列表框,但我不知道如何将转换后的文本放入一个控件中,让用户 select 显示文本。这是我拥有的:
<ListBox Name="FinishedTestErrorsListBox"
FontSize="12"
ItemsSource="{Binding Path=SelectedComparisonResult.TestFailItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Converter={StaticResource testFailItemConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我试过向 DataTemplate 添加一个 TextBox,如下所示...
<TextBlock Text="{Binding Converter={StaticResource testFailItemConverter}}"/>
... 但这会产生一个运行时错误,这是由于向转换器发送了错误类型的对象而引起的。我知道这里我没有正确设置转换器绑定,但我不太了解我应该如何在这里设置绑定或者为什么这会导致错误。
那么,我的问题是:
我可以使用什么内容容器让用户 select 来自各个 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}}"/>
试试这个。 TextBlock 不支持文本选择,但 TextBox 支持。您只需将其设置为只读,这样用户就无法修改文本,并更改其边框粗细和背景,使其看起来像标签:
<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吗?您可以 select 文本框内的文本。路径必须更改为 Path=.
<TextBox Text="{Binding Path=., Converter={StaticResource testFailItemConverter}}" />
没有多少代码可以使用,但这段代码对我有用:
xaml:
<Window x:Class="WhosebugTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:WhosebugTest"
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;
}
}