【问题标题】:Select/Copy text over several items in an ItemsControl在 ItemsControl 中的多个项目上选择/复制文本
【发布时间】:2016-06-29 15:38:09
【问题描述】:

我有一个“控制台仿真”,如下所示: https://stackoverflow.com/a/14957478/6518526

我的控制台没有交互性,所以它实际上只是一个正在显示的缓冲区。

所以有一个ScrollViewer 包含一个ItemsControl,其中包含TextBlocks 的。 ItemsControl 通过将数据绑定到包含字符串的可观察队列来获取其数据。

如何扩展此设置,以便可以像在控制台中一样选择/复制文本?

我已经尝试使用TextBox 而不是TextBlock,但这只是让我可以在每个项目中进行选择,但不能同时在多个项目中进行选择。

我还在这里找到了这个解决方案,它实现了一种使用数据绑定在 FlowDocument 中填充控件的方法:https://msdn.microsoft.com/en-us/magazine/dd569761.aspx。 但看起来,这种方法也不会让我对多个项目进行选择。

所以,我不知道可以以何种方式使用哪个 Control 来实现这一点。

【问题讨论】:

  • 您需要选择一个项目的一部分、下一个项目的全部、以及之后的项目的一部分吗?或者你能忍受离散地选择项目,每个项目要么完全选择,要么完全不选择?如果是前者,您需要一个多行只读文本框(在您的视图模型中使用代码来加入行的选择并将结果作为属性公开)。如果是后者,我建议使用 ListBox。事实上,join/multiline-textbox 是迄今为止最简单的解决方案:一旦加入所需的行,其余的都是免费的。
  • 理想的是能够进行任意选择,所以看起来加入/多行文本框是要走的路。您能否详细说明您是如何将选择线/暴露作为属性加入的部分?
  • 我的意思是,如果你有,比如public ObservableCollection<String> Lines { ... },你也可以拥有public String Text { get { return String.Join("\n", Lines); } },并在Lines 更改时适当提高PropertyChanged。然后在 XAML <TextBox Text="{Binding Text}" ... /> 中,在文本框上使用适当的其他属性进行多行等。
  • 好的,现在你的意思很清楚了。我实际上担心性能会这样,但事实证明我的负载没有问题。您能否将您的评论放入答案中以便我接受?

标签: c# wpf console emulation


【解决方案1】:

如果您想让用户从多行文本中选择和复制任意连续的字符子集,最简单的解决方案是多行TextBox。在您的情况下,您会将其设为只读。

如果您有足够多的行集合,这将陷入困境,但对于可管理的文本数量,它应该没问题。看看它如何与您正在处理的案例一起使用。

如果你想将你的文本作为一个集合来维护(如果是谨慎的行)(在这种情况下这听起来是个好主意),你可以简单地编写一个属性,在 Lines 集合发生变化时将这些行连接成一个字符串:

C#

public MyViewModel()
{
    Lines = new ObservableCollection<String>();
}

private ObservableCollection<String> _lines;
public ObservableCollection<String> Lines
{
    get { return _lines; }
    protected set {
        _lines = value;
        UpdateText();
        _lines.CollectionChanged += _lines_CollectionChanged;
        OnPropertyChanged("Lines");
    }
}

private void UpdateText()
{
    Text = String.Join("\n", Lines);
}

private void _lines_CollectionChanged(object sender, 
    System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    UpdateText();
}

private string _text;
public String Text {
    get { return _text; }
    protected set {
        _text = value;
        OnPropertyChanged("Text");
    }
}

XAML

<Grid>
    <TextBox 
        Text="{Binding Text}" 
        TextWrapping="Wrap"
        AcceptsReturn="True"
        IsReadOnly="True"
        />
</Grid>

您甚至不需要编写自己的上下文菜单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    相关资源
    最近更新 更多