依赖环境

功能建议 · 134 次浏览
cat poo 创建于 2026-07-17 13:31

能不能运行自动下载一下,Microsoft.Data.Sqlite 和 SQLitePCL 相关程序集,一般人电脑里没有这些


cat poo 2026-07-17 13:43 :

//css_ref System.Data.SQLite.dll
//css_ref Newtonsoft.Json.dll
//css_ref WindowsBase.dll
//css_ref PresentationCore.dll

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;      // 替换 Microsoft.Data.Sqlite
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Quicker.Public;

public static class Script
{
    private const int PageSize = 100;
    private const int ResultCellPreviewLength = 120;
    private const double ResultColumnMaxWidth = 280;

    private static readonly IValueConverter ResultPreviewConverter = new ResultPreviewValueConverter();

    private sealed class ResultPreviewValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var text = value as string;
            return text == null ? value : GetResultCellPreview(text);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    }

    private const string ObjectListSql =
        "SELECT name, type " +
        "FROM sqlite_master " +
        "WHERE type IN ('table', 'view') " +
        "AND name NOT LIKE 'sqlite_%' " +
        "ORDER BY name COLLATE NOCASE";

    // ---------- 入口方法 ----------
    public static void OnWindowCreated(
        Window win,
        IDictionary<string, object> dataContext,
        ICustomWindowContext winContext)
    {
        // 初始化数据上下文默认值
        dataContext["objectList"] = new DataTable();
        dataContext["queryResult"] = new DataTable();
        dataContext["fullQueryResult"] = new DataTable();
        dataContext["resultSchemaKey"] = "";
        dataContext["selectedObject"] = "";
        dataContext["sql"] = "";
        dataContext["pageSize"] = PageSize;
        dataContext["pageOffset"] = 0;
        dataContext["totalRowCount"] = 0L;
        dataContext["rowCountCache"] = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
        dataContext["sortColumn"] = "";
        dataContext["sortDescending"] = false;
        dataContext["isTablePreview"] = false;
        dataContext["currentCellCaption"] = "";
        dataContext["currentCellValue"] = "";
        dataContext["hasCurrentCell"] = false;

        SetObjectList(win, dataContext, (DataTable)dataContext["objectList"]);
        SetResultGrid(win, dataContext, (DataTable)dataContext["queryResult"]);
        SetCurrentObject(win, dataContext, "选择一个表或视图");
        SetPageText(win, 0, PageSize, 0, 0L);
        SetCellValue(win, dataContext, "单击上方表格中的单元格以查看完整值", "", false);
        SetStatus(win, dataContext, "正在加载数据库对象...");

        // ---------- ObjectList 选择事件 ----------
        var objectList = win.FindName("ObjectList") as ListBox;
        if (objectList != null)
        {
            objectList.SelectionChanged += delegate (object sender, SelectionChangedEventArgs e)
            {
                var row = objectList.SelectedItem as DataRowView;
                if (row == null || row.Row == null) return;

                var objectName = Convert.ToString(row["name"]);
                dataContext["sortColumn"] = "";
                dataContext["sortDescending"] = false;
                ClearSortIndicators(win.FindName("ResultGrid") as DataGrid);
                LoadObjectPage(win, dataContext, objectName, 0, false);
            };
        }

        // ---------- ResultGrid 事件 ----------
        var resultGrid = win.FindName("ResultGrid") as DataGrid;
        if (resultGrid != null)
        {
            resultGrid.AutoGeneratingColumn += delegate (object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
                e.Column.MaxWidth = ResultColumnMaxWidth;
                var textColumn = e.Column as DataGridTextColumn;
                if (textColumn != null)
                {
                    var binding = textColumn.Binding as Binding;
                    if (binding != null)
                        binding.Converter = ResultPreviewConverter;

                    var style = new Style(typeof(TextBlock));
                    style.Setters.Add(new Setter(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis));
                    textColumn.ElementStyle = style;
                }
            };

            resultGrid.LoadingRow += delegate (object sender, DataGridRowEventArgs e)
            {
                var pageOffset = GetInteger(dataContext, "pageOffset", 0);
                e.Row.Header = (pageOffset + e.Row.GetIndex() + 1).ToString();
            };

            resultGrid.SelectedCellsChanged += delegate (object sender, SelectedCellsChangedEventArgs e)
            {
                if (e.AddedCells.Count == 0) return;
                var cell = e.AddedCells[0];
                try
                {
                    ShowCellValue(win, dataContext, cell.Item as DataRowView, cell.Column);
                }
                catch (Exception ex)
                {
                    SetStatus(win, dataContext, "读取单元格失败:" + ex.Message);
                }
            };

            resultGrid.Sorting += delegate (object sender, DataGridSortingEventArgs e)
            {
                e.Handled = true;

                if (!GetBoolean(dataContext, "isTablePreview"))
                {
                    SetStatus(win, dataContext, "请先从左侧选择表或视图");
                    return;
                }

                var columnName = GetColumnName(e.Column);
                var sameColumn = String.Equals(
                    GetText(dataContext, "sortColumn"),
                    columnName,
                    StringComparison.OrdinalIgnoreCase);
                var currentDescending = GetBoolean(dataContext, "sortDescending");
                if (sameColumn && currentDescending)
                {
                    dataContext["sortColumn"] = "";
                    dataContext["sortDescending"] = false;
                }
                else
                {
                    dataContext["sortColumn"] = columnName;
                    dataContext["sortDescending"] = sameColumn;
                }

                var selectedObject = GetText(dataContext, "selectedObject");
                if (!String.IsNullOrWhiteSpace(selectedObject))
                    LoadObjectPage(win, dataContext, selectedObject, 0, false);
            };
        }

        RefreshObjects(win, dataContext);
    }

    // ---------- 按钮点击处理 ----------
    public static bool OnButtonClicked(
        string controlName,
        object controlTag,
        Window win,
        IDictionary<string, object> dataContext,
        ICustomWindowContext winContext)
    {
        if (controlName == "btnRefreshObjects")
        {
            RefreshObjects(win, dataContext);
            return true;
        }

        if (controlName == "btnCopyCell")
        {
            CopyCurrentCell(win, dataContext);
            return true;
        }

        var selectedObject = GetText(dataContext, "selectedObject");
        var pageSize = PageSize;
        var pageOffset = GetInteger(dataContext, "pageOffset", 0);

        if (controlName == "btnPrevious")
        {
            if (String.IsNullOrWhiteSpace(selectedObject))
            {
                SetStatus(win, dataContext, "请先选择一个表或视图");
                return true;
            }
            LoadObjectPage(win, dataContext, selectedObject, Math.Max(0, pageOffset - pageSize), false);
            return true;
        }

        if (controlName == "btnNext")
        {
            if (String.IsNullOrWhiteSpace(selectedObject))
            {
                SetStatus(win, dataContext, "请先选择一个表或视图");
                return true;
            }
            LoadObjectPage(win, dataContext, selectedObject, pageOffset + pageSize, true);
            return true;
        }

        if (controlName == "btnRunSql")
        {
            RunCustomSelect(win, dataContext);
            return true;
        }

        return false;
    }

    // ---------- 核心数据访问(使用 System.Data.SQLite) ----------
    private static bool TryQuery(string dbPath, string sql, out DataTable table, out int rowCount, out string error)
    {
        table = new DataTable();
        rowCount = 0;
        error = "未知错误";

        if (String.IsNullOrWhiteSpace(dbPath))
        {
            error = "没有选择数据库文件";
            return false;
        }

        if (String.IsNullOrWhiteSpace(sql))
        {
            error = "SQL 不能为空";
            return false;
        }

        try
        {
            var connectionString = new SQLiteConnectionStringBuilder
            {
                DataSource = dbPath,
                ReadOnly = true,
                Pooling = true
            }.ToString();

            using (var connection = new SQLiteConnection(connectionString))
            using (var command = connection.CreateCommand())
            {
                command.CommandText = sql;
                command.CommandTimeout = 30;
                connection.Open();
                using (var reader = command.ExecuteReader())
                {
                    table.Load(reader);
                }
            }

            rowCount = table.Rows.Count;
            error = "";
            return true;
        }
        catch (Exception ex)
        {
            error = ex.Message;
            return false;
        }
    }

    private static bool TryGetObjectRowCount(string dbPath, string objectName, out long totalRowCount, out string error)
    {
        totalRowCount = 0L;
        var countSql = "SELECT COUNT(*) AS total_rows FROM " + QuoteIdentifier(objectName);

        DataTable countTable;
        int ignoredRowCount;
        if (!TryQuery(dbPath, countSql, out countTable, out ignoredRowCount, out error))
            return false;

        if (countTable.Rows.Count == 0 || !countTable.Columns.Contains("total_rows"))
        {
            error = "总行数查询没有返回 total_rows";
            return false;
        }

        try
        {
            totalRowCount = Convert.ToInt64(countTable.Rows[0]["total_rows"]);
            error = "";
            return true;
        }
        catch (Exception ex)
        {
            error = ex.Message;
            return false;
        }
    }

    // ---------- 业务逻辑方法(保持不变) ----------
    private static void RefreshObjects(Window win, IDictionary<string, object> dataContext)
    {
        SetStatus(win, dataContext, "正在读取表和视图...");

        DataTable table;
        int rowCount;
        string error;
        if (!TryQuery(GetText(dataContext, "dbPath"), ObjectListSql, out table, out rowCount, out error))
        {
            SetObjectList(win, dataContext, new DataTable());
            dataContext["selectedObject"] = "";
            dataContext["pageOffset"] = 0;
            dataContext["totalRowCount"] = 0L;
            dataContext["rowCountCache"] = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
            dataContext["sortColumn"] = "";
            dataContext["sortDescending"] = false;
            dataContext["isTablePreview"] = false;
            SetResultGrid(win, dataContext, new DataTable());
            ClearSortIndicators(win.FindName("ResultGrid") as DataGrid);
            SetCurrentObject(win, dataContext, "选择一个表或视图");
            SetPageText(win, 0, PageSize, 0, 0L);
            SetCellValue(win, dataContext, "单击上方表格中的单元格以查看完整值", "", false);
            SetStatus(win, dataContext, "读取对象失败:" + error);
            return;
        }

        SetObjectList(win, dataContext, table);
        dataContext["selectedObject"] = "";
        dataContext["pageOffset"] = 0;
        dataContext["totalRowCount"] = 0L;
        dataContext["rowCountCache"] = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
        dataContext["sortColumn"] = "";
        dataContext["sortDescending"] = false;
        dataContext["isTablePreview"] = false;
        SetResultGrid(win, dataContext, new DataTable());
        ClearSortIndicators(win.FindName("ResultGrid") as DataGrid);
        SetCurrentObject(win, dataContext, "选择一个表或视图");
        SetPageText(win, 0, PageSize, 0, 0L);
        SetCellValue(win, dataContext, "单击上方表格中的单元格以查看完整值", "", false);
        SetStatus(win, dataContext, "已发现 " + rowCount + " 个表或视图");
    }

    private static void LoadObjectPage(Window win, IDictionary<string, object> dataContext, string objectName, int offset, bool keepCurrentPageWhenEmpty)
    {
        if (String.IsNullOrWhiteSpace(objectName))
        {
            SetStatus(win, dataContext, "未取得对象名称");
            return;
        }

        var pageSize = PageSize;
        offset = Math.Max(0, offset);
        var orderBy = GetTableOrderBy(GetText(dataContext, "sortColumn"), GetBoolean(dataContext, "sortDescending"));
        var sql = "SELECT * FROM " + QuoteIdentifier(objectName) + orderBy +
                  " LIMIT " + pageSize + " OFFSET " + offset;

        SetStatus(win, dataContext, "正在读取 " + objectName + "...");

        DataTable table;
        int rowCount;
        string error;
        if (!TryQuery(GetText(dataContext, "dbPath"), sql, out table, out rowCount, out error))
        {
            SetStatus(win, dataContext, "查询失败:" + error);
            return;
        }

        var rowCountCache = GetRowCountCache(dataContext);
        long totalRowCount;
        if (!rowCountCache.TryGetValue(objectName, out totalRowCount))
        {
            string countError;
            if (TryGetObjectRowCount(GetText(dataContext, "dbPath"), objectName, out totalRowCount, out countError))
            {
                rowCountCache[objectName] = totalRowCount;
            }
            else
            {
                totalRowCount = -1L;
                rowCountCache[objectName] = totalRowCount;
            }
        }

        dataContext["totalRowCount"] = totalRowCount;

        if (keepCurrentPageWhenEmpty && rowCount == 0)
        {
            SetStatus(win, dataContext, "已是最后一页");
            return;
        }

        dataContext["selectedObject"] = objectName;
        dataContext["pageOffset"] = offset;
        dataContext["isTablePreview"] = true;
        SetCurrentObject(win, dataContext, objectName);
        SetSqlText(win, dataContext, sql);
        SetResultGrid(win, dataContext, table);
        ApplyCurrentSortIndicator(win.FindName("ResultGrid") as DataGrid, GetText(dataContext, "sortColumn"), GetBoolean(dataContext, "sortDescending"));
        SetCellValue(win, dataContext, "单击上方表格中的单元格以查看完整值", "", false);
        SetPageText(win, offset, pageSize, rowCount, totalRowCount);
        SetStatus(win, dataContext,
            "已加载 " + objectName + ",本页 " + rowCount + " 行" +
            (totalRowCount >= 0 ? ",总计 " + totalRowCount + " 行" : ",总行数读取失败"));
    }

    private static void RunCustomSelect(Window win, IDictionary<string, object> dataContext)
    {
        var sql = GetText(dataContext, "sql");
        if (String.IsNullOrWhiteSpace(sql))
        {
            SetStatus(win, dataContext, "请输入一条 SELECT 查询");
            return;
        }

        if (!IsSingleSelect(sql))
        {
            SetStatus(win, dataContext, "只允许单条 SELECT 查询,且不要输入分号");
            return;
        }

        SetStatus(win, dataContext, "正在执行自定义查询...");

        DataTable table;
        int rowCount;
        string error;
        if (!TryQuery(GetText(dataContext, "dbPath"), sql, out table, out rowCount, out error))
        {
            SetStatus(win, dataContext, "查询失败:" + error);
            return;
        }

        dataContext["pageOffset"] = 0;
        SetResultGrid(win, dataContext, table);
        dataContext["isTablePreview"] = false;
        SetCurrentObject(win, dataContext, "自定义 SELECT 查询");
        SetCellValue(win, dataContext, "单击上方表格中的单元格以查看完整值", "", false);
        SetPageText(win, 0, PageSize, rowCount, (long)rowCount);
        SetStatus(win, dataContext, "自定义查询完成,共 " + rowCount + " 行");
    }

    // ---------- 辅助方法 ----------
    private static bool IsSingleSelect(string sql)
    {
        var text = sql.TrimStart();
        if (text.IndexOf(';') >= 0 || !text.StartsWith("select", StringComparison.OrdinalIgnoreCase))
            return false;
        if (text.Length == 6) return false;
        var nextChar = text[6];
        return !Char.IsLetterOrDigit(nextChar) && nextChar != '_';
    }

    private static string QuoteIdentifier(string identifier)
    {
        return "\"" + identifier.Replace("\"", "\"\"") + "\"";
    }

    private static string GetColumnName(DataGridColumn column)
    {
        if (column == null) return "";
        if (!String.IsNullOrWhiteSpace(column.SortMemberPath))
            return column.SortMemberPath;
        return RemoveSortArrow(Convert.ToString(column.Header));
    }

    private static string RemoveSortArrow(string header)
    {
        var text = header ?? "";
        if (text.EndsWith(" ▲") || text.EndsWith(" ▼"))
            return text.Substring(0, text.Length - 2);
        return text;
    }

    private static string GetTableOrderBy(string columnName, bool descending)
    {
        if (String.IsNullOrWhiteSpace(columnName)) return "";
        return " ORDER BY " + QuoteIdentifier(columnName) + (descending ? " DESC" : " ASC");
    }

    private static void SetSortIndicator(DataGrid grid, DataGridColumn activeColumn, bool descending)
    {
        if (grid == null) return;
        foreach (DataGridColumn column in grid.Columns)
        {
            var columnName = GetColumnName(column);
            column.Header = column == activeColumn
                ? columnName + (descending ? " ▼" : " ▲")
                : columnName;
        }
    }

    private static void ClearSortIndicators(DataGrid grid)
    {
        if (grid == null) return;
        foreach (DataGridColumn column in grid.Columns)
            column.Header = GetColumnName(column);
    }

    private static void ApplyCurrentSortIndicator(DataGrid grid, string sortColumn, bool descending)
    {
        ClearSortIndicators(grid);
        if (grid == null || String.IsNullOrWhiteSpace(sortColumn)) return;
        foreach (DataGridColumn column in grid.Columns)
        {
            if (String.Equals(GetColumnName(column), sortColumn, StringComparison.OrdinalIgnoreCase))
            {
                SetSortIndicator(grid, column, descending);
                return;
            }
        }
    }

    private static string GetText(IDictionary<string, object> dataContext, string key)
    {
        object value;
        return dataContext.TryGetValue(key, out value) && value != null ? Convert.ToString(value) : "";
    }

    private static int GetInteger(IDictionary<string, object> dataContext, string key, int defaultValue)
    {
        object value;
        if (!dataContext.TryGetValue(key, out value) || value == null)
            return defaultValue;
        try { return Convert.ToInt32(value); }
        catch { return defaultValue; }
    }

    private static long GetLong(IDictionary<string, object> dataContext, string key, long defaultValue)
    {
        object value;
        if (!dataContext.TryGetValue(key, out value) || value == null)
            return defaultValue;
        try { return Convert.ToInt64(value); }
        catch { return defaultValue; }
    }

    private static Dictionary<string, long> GetRowCountCache(IDictionary<string, object> dataContext)
    {
        object value;
        var cache = dataContext.TryGetValue("rowCountCache", out value)
            ? value as Dictionary<string, long>
            : null;
        if (cache != null) return cache;
        cache = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
        dataContext["rowCountCache"] = cache;
        return cache;
    }

    private static bool GetBoolean(IDictionary<string, object> dataContext, string key)
    {
        object value;
        if (!dataContext.TryGetValue(key, out value) || value == null) return false;
        try { return Convert.ToBoolean(value); }
        catch { return false; }
    }

    private static void SetObjectList(Window win, IDictionary<string, object> dataContext, DataTable table)
    {
        dataContext["objectList"] = table;
        var list = win.FindName("ObjectList") as ListBox;
        if (list != null) list.ItemsSource = table.DefaultView;
    }

    private static void SetResultGrid(Window win, IDictionary<string, object> dataContext, DataTable table)
    {
        dataContext["fullQueryResult"] = table;
        dataContext["queryResult"] = table;

        var schemaKey = GetResultSchemaKey(table);
        var schemaChanged = !String.Equals(GetText(dataContext, "resultSchemaKey"), schemaKey, StringComparison.Ordinal);
        dataContext["resultSchemaKey"] = schemaKey;

        var grid = win.FindName("ResultGrid") as DataGrid;
        if (grid != null)
        {
            if (schemaChanged)
            {
                grid.ItemsSource = null;
                grid.Columns.Clear();
            }
            grid.ItemsSource = table.DefaultView;
        }
    }

    private static string GetResultSchemaKey(DataTable table)
    {
        if (table == null || table.Columns.Count == 0) return "";
        var parts = new string[table.Columns.Count];
        foreach (DataColumn column in table.Columns)
        {
            var typeName = column.DataType == null ? "" : column.DataType.FullName;
            parts[column.Ordinal] = column.ColumnName + "\u001f" + typeName;
        }
        return String.Join("\u001e", parts);
    }

    private static string GetResultCellPreview(string value)
    {
        if (String.IsNullOrEmpty(value) || value.Length <= ResultCellPreviewLength)
            return value;
        return value.Substring(0, ResultCellPreviewLength) + "...";
    }

    private static DataTable GetFullQueryResult(IDictionary<string, object> dataContext)
    {
        object value;
        return dataContext.TryGetValue("fullQueryResult", out value) ? value as DataTable : null;
    }

    private static DataColumn FindDataColumn(DataTable table, string columnName)
    {
        if (table == null || String.IsNullOrWhiteSpace(columnName)) return null;
        foreach (DataColumn column in table.Columns)
        {
            if (String.Equals(column.ColumnName, columnName, StringComparison.OrdinalIgnoreCase))
                return column;
        }
        return null;
    }

    private static void ShowCellValue(Window win, IDictionary<string, object> dataContext, DataRowView row, DataGridColumn column)
    {
        if (row == null || row.Row == null || column == null) return;

        var columnName = column.SortMemberPath;
        if (String.IsNullOrWhiteSpace(columnName))
            columnName = Convert.ToString(column.Header);

        var displayedColumn = FindDataColumn(row.Row.Table, columnName);
        if (displayedColumn == null)
        {
            SetStatus(win, dataContext, "无法识别单击单元格的列名");
            return;
        }

        var sourceValue = row.Row[displayedColumn];
        var displayedTable = row.Row.Table;
        var rowIndex = displayedTable.Rows.IndexOf(row.Row);
        var fullTable = GetFullQueryResult(dataContext);
        var fullColumn = FindDataColumn(fullTable, displayedColumn.ColumnName);
        if (fullTable != null && rowIndex >= 0 && rowIndex < fullTable.Rows.Count && fullColumn != null)
            sourceValue = fullTable.Rows[rowIndex][fullColumn];

        var value = FormatCellValue(sourceValue);
        SetCellValue(win, dataContext, "列:" + displayedColumn.ColumnName, value, true);
        SetStatus(win, dataContext, "已显示 " + displayedColumn.ColumnName + " 的完整值");
    }

    private static void CopyCurrentCell(Window win, IDictionary<string, object> dataContext)
    {
        if (!GetBoolean(dataContext, "hasCurrentCell"))
        {
            SetStatus(win, dataContext, "请先单击表格中的一个单元格");
            return;
        }

        try
        {
            Clipboard.SetText(GetText(dataContext, "currentCellValue"));
            SetStatus(win, dataContext, "已复制当前数据项");
        }
        catch (Exception ex)
        {
            SetStatus(win, dataContext, "复制失败:" + ex.Message);
        }
    }

    private static string FormatCellValue(object value)
    {
        if (value == null || value == DBNull.Value) return "NULL";
        var bytes = value as byte[];
        if (bytes != null) return Convert.ToBase64String(bytes);
        return FormatJsonIfPossible(Convert.ToString(value));
    }

    private static string FormatJsonIfPossible(string value)
    {
        if (String.IsNullOrWhiteSpace(value)) return value;
        var text = value.Trim();
        if (!((text.StartsWith("{") && text.EndsWith("}")) || (text.StartsWith("[") && text.EndsWith("]"))))
            return value;

        try { return JToken.Parse(text).ToString(Formatting.Indented); }
        catch (JsonReaderException) { return value; }
    }

    private static void SetCellValue(Window win, IDictionary<string, object> dataContext, string caption, string value, bool hasValue)
    {
        dataContext["currentCellCaption"] = caption;
        dataContext["currentCellValue"] = value;
        dataContext["hasCurrentCell"] = hasValue;

        var captionText = win.FindName("CellCaptionText") as TextBlock;
        if (captionText != null) captionText.Text = caption;

        var valueBox = win.FindName("CellValueBox") as TextBox;
        if (valueBox != null) valueBox.Text = value;
    }

    private static void SetSqlText(Window win, IDictionary<string, object> dataContext, string sql)
    {
        dataContext["sql"] = sql;
        var sqlBox = win.FindName("SqlBox") as TextBox;
        if (sqlBox != null) sqlBox.Text = sql;
    }

    private static void SetCurrentObject(Window win, IDictionary<string, object> dataContext, string text)
    {
        var label = win.FindName("CurrentObjectText") as TextBlock;
        if (label != null) label.Text = text;
    }

    private static void SetPageText(Window win, int offset, int pageSize, int rowCount, long totalRowCount)
    {
        var label = win.FindName("PageText") as TextBlock;
        if (label == null) return;

        var pageNumber = offset / Math.Max(1, pageSize) + 1;
        var totalText = totalRowCount >= 0 ? ",共 " + totalRowCount + " 行" : ",总行数未知";
        if (rowCount == 0)
        {
            label.Text = "第 " + pageNumber + " 页,0 行" + totalText;
            return;
        }
        label.Text = "第 " + pageNumber + " 页,第 " + (offset + 1) + " - " + (offset + rowCount) + " 行" + totalText;
    }

    private static void SetStatus(Window win, IDictionary<string, object> dataContext, string status)
    {
        dataContext["status"] = status;
        var label = win.FindName("StatusText") as TextBlock;
        if (label != null) label.Text = status;
    }
}找ai写的仅依赖quicker自带的System.Data.SQLite.dll来达到同样的效果,放进自定义窗口辅助C#代码里替换就行

h0zr 2026-07-17 15:48 :

啊??2.0自带了这些模块了吧,这是2.0自带的和sqlite相关的模块


你不会用的是1.45吧?



h0zr 最后更新于 2026-07-17 19:14
cat poo 回复 h0zr 2026-07-21 11:23 :
欧欧,2.0都出来了,啥时候的事,我瞧瞧去
回复内容
h0zr 2026-07-17 21:22
#1

更新了个新版本,兼容1.x和2.0

回复主贴