ユーザーがリモートサーバーに送信される数字のグリッドを貼り付けることができる UI アプリを作成しています。クライアントは WPF または Silverlight です。
文字列内のタブ区切りの行からコントロールに変換して、ユーザーの貼り付け入力をフックするためにGrid
使用するTextbox
コントロールを試しました。ユーザーが Excel からわずか 122x161 のセルを貼り付けた後、これが更新されるまでに 12 秒 (!) かかりますが、これは容認できないほど遅いです。文字列の分析には 0.1 秒、行と列の追加には 1 秒、コントロールの作成と挿入には 2 秒かかり、残りの 12 秒は最初のコントロールの描画に費やされたようです。DataObject.AddPastingHandler
Textbox
TextBox
TextBox
私も試してみましDataGrid
たが、リフレクションを使用してプロパティを分析するオブジェクトの 1D 配列を優先して、2D 配列をうまく処理していないようです。
今、私は a を使ってCanvas
自分で数字を描くことを考えていますが、それは正気ではないようです。組み込みの WPF または Silverlight コントロールを使用して、ユーザーに苦痛を与えることなくこれを行う簡単な方法はありますか?
編集
TextBox
それ以来、めちゃくちゃ遅いので、私は犯人として特定しました。問題を示すいくつかの F# コードを次に示します ( を に置き換えるTextBox
とTextBlock
、40 倍高速になります。これは、本来よりも桁違いに遅くなりますが、このインスタンスでは許容されます)。
open System.Windows
let app = Application()
let readClipboard() =
let data = (Clipboard.GetData "Text") :?> string
[|for row in data.Split[|'\n'|] do
match row.Split[|'\t'|] with
| [||] | [|""|] -> ()
| row -> yield row|]
[<System.STAThreadAttribute>]
do
let grid = Controls.Grid()
let row = Controls.RowDefinition()
Controls.RowDefinition() |> grid.RowDefinitions.Add
Controls.ColumnDefinition() |> grid.ColumnDefinitions.Add
let add i j ctrl =
Controls.Grid.SetRow(ctrl, i)
Controls.Grid.SetColumn(ctrl, j)
grid.Children.Add ctrl |> ignore
let paste() =
let timer = System.Diagnostics.Stopwatch.StartNew()
let data = readClipboard()
printfn "Read clipboard %fs" timer.Elapsed.TotalSeconds
let rows = data.Length
let cols = data |> Array.fold (fun n xs -> xs.Length |> max n) 0
printfn "%dx%d" rows cols
grid.RowDefinitions.Clear()
grid.ColumnDefinitions.Clear()
grid.Children.Clear()
for row in 1..rows do
Controls.RowDefinition(Height=GridLength 24.0) |> grid.RowDefinitions.Add
for col in 1..cols do
Controls.ColumnDefinition(Width=GridLength 64.0) |> grid.ColumnDefinitions.Add
printfn "Add rows and columns complete %fs" timer.Elapsed.TotalSeconds
for i in 0..rows-1 do
for j in 0..data.[i].Length-1 do
Controls.TextBox(Text=data.[i].[j]) |> add i j
printfn "Insert complete %fs" timer.Elapsed.TotalSeconds
Media.CompositionTarget.Rendering.Add(fun _ ->
printfn "Next Rendering event at %fs" timer.Elapsed.TotalSeconds
app.Shutdown())
let scroll = Controls.ScrollViewer(Content=grid)
scroll.HorizontalScrollBarVisibility <- Controls.ScrollBarVisibility.Visible
let window = Window(Content=scroll)
window.Focusable <- true
window.Focus() |> ignore
window.PreviewKeyDown.Add(fun e ->
let ctrl = Input.ModifierKeys.Control
if Input.Keyboard.Modifiers &&& ctrl = ctrl then
if e.Key = Input.Key.V then
paste())
app.Run window |> ignore