【问题标题】:Making Table row focus and loose focus using event handlers using c# in wpf app在 wpf 应用程序中使用 c# 使用事件处理程序使表格行焦点和松散焦点
【发布时间】:2018-06-27 08:00:48
【问题描述】:

我在 FlowDocument 中放置了一个表格。我在后端使用 c# 动态地将数据添加到表中。我已附加事件处理程序以聚焦一行,但如果用户单击该行以外的任何位置,我将面临移除焦点的问题。

我的 XAML 代码是这样的:

<FlowDocumentScrollViewer Width="auto">
                <FlowDocument>
                    <Table x:Name="feedTable">
                        <Table.Columns>
                            <TableColumn Width="*"/>
                            <TableColumn Width="3*"/>
                            <TableColumn Width="2*"/>
                            <TableColumn Width="4*"/>
                            <TableColumn Width="*"/>
                        </Table.Columns>
                        <TableRowGroup>
                            <TableRow>
                                <TableCell>
                                    <Paragraph FontSize="14pt" FontWeight="Bold">On</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="14pt" FontWeight="Bold">Feed Link</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="14pt" FontWeight="Bold">Site</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="14pt" FontWeight="Bold">Title</Paragraph>
                                </TableCell>
                                <TableCell>
                                    <Paragraph FontSize="14pt" FontWeight="Bold">Feeds</Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                        <TableRowGroup x:Name="feedTableRowGroup">

                        </TableRowGroup>
                    </Table>
                </FlowDocument>
            </FlowDocumentScrollViewer>

这就是我在从 db 获取数据后将数据添加到后端表的方式

for (int i = 0; i < data.Rows.Count; i++)
        {
            feedTableRowGroup.Rows.Add(new TableRow());
            var currentRow = feedTableRowGroup.Rows[feedTableRowGroup.Rows.Count - 1];

            CheckBox checkBox = new CheckBox();
            checkBox.Tag = ((int)data.Rows[i]["id"]).ToString();
            checkBox.IsChecked = (byte)data.Rows[i]["is_enabled"] == 1 ? true : false;

            Paragraph paragraph = new Paragraph();
            paragraph.Inlines.Add(checkBox);

            int maxChars = 25;
            string link = (string)data.Rows[i]["link"];
            link = link.Length <= maxChars ? link : link.Substring(0, maxChars) + "....";

            currentRow.Cells.Add(new TableCell(paragraph));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run(link))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run((string)data.Rows[i]["site_name"]))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run((string)data.Rows[i]["title"]))));
            currentRow.Cells.Add(new TableCell(new Paragraph(new Run(((int)data.Rows[i]["items_count"]).ToString()))));

            currentRow.MouseDown += new MouseButtonEventHandler(FocusTableRow);

        }

当我单击“currentRow.MouseDown”时,它会将焦点添加到该行,但现在每当我单击另一个空白区域时,我都想移除此焦点。

我已经创建了用于添加和删除焦点的事件处理程序,我正在添加焦点,但现在我需要一种方法来删除这个焦点

private void FocusTableRow(object sender, RoutedEventArgs e)
    {
       sender.GetType().GetProperty("Background").SetValue(sender, Brushes.LightGray);    
    }

    private void NonFocusTableRow(object sender, RoutedEventArgs e)
    {
        sender.GetType().GetProperty("Background").SetValue(sender, Brushes.White);
    }

我可以使用任何 eventhadler 来分配以从行中移除此焦点吗?

【问题讨论】:

    标签: c# wpf desktop-application


    【解决方案1】:

    我不完全确定您对一行的“焦点”是什么意思,因为您的所有代码都在用不同的背景颜色突出显示该行(在谈到 GUI 时,焦点意味着不同的东西)。但是假设这是意图并假设一次只能“集中”一行,那么有多种方法可以完成您所描述的内容。我不一定会这样做,但在不从您提供的内容中了解更多关于您的代码和数据的情况下......

    首先,当您突出显示指定行时,关闭所有其他行的突出显示...

    private void FocusTableRow (object sender, RoutedEventArgs e)
    {
        sender.GetType ().GetProperty ("Background").SetValue (sender, Brushes.LightGray);
    
        foreach (var row in feedTableRowGroup.Rows) {
            if (row != sender) {
                row.GetType ().GetProperty ("Background").SetValue (row, Brushes.White);
            }
        }
    
        e.Handled = true;
    }
    

    我还添加了 e.Handled = true 来表示我们处理了鼠标按下事件并阻止其他人处理它。

    然后将 MouseDown 处理程序添加到 feedTable(在 ctor 中或您正在初始化数据的位置)以在单击行外时捕获并“关闭”所有行突出显示...

    feedTable.MouseDown += FeedTable_MouseDown;
    

    ...

    private void FeedTable_MouseDown (object sender, MouseButtonEventArgs e)
    {
        foreach (var row in feedTableRowGroup.Rows) {
            row.GetType ().GetProperty ("Background").SetValue (row, Brushes.White);
        }
    }
    

    再次,不是我会做的方式,也可能不是对 WPF 最友好的方法,但它会与您提供给我们的内容一起使用。这听起来像是 MVVM 架构的一个很好的候选者,尽管它需要稍微重构你的所有代码。

    【讨论】:

    • 有没有一种方法可以做到这一点,而无需手动取消突出显示所有其他行?
    • 如果您没有被锁定到 FlowControlDocument 类集,您可以使用 ItemsControl 派生控件之一(即 ListView)甚至 DataGrid。所有这些都支持项目选择(多行和单行),并且可以设置为自动突出显示。可能有一种方法可以使用 TableRowGroup 的东西来做你想做的事,但你超出了我对 Flow 控件的了解。
    • 感谢@Jeff 花时间回答我的问题。我现在将自己进一步研究。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多