我正在編寫一個UI應用程序,允許用戶將數字網格粘貼到該應用程序中,並將其發送到遠程服務器。客戶端可以是WPF或Silverlight。用於查看122x161數字網格的WPF/Silverlight控件
我使用DataObject.AddPastingHandler
鉤住使用者粘貼輸入,在一個字符串從製表符分隔的行轉換爲Textbox
控制試圖Textbox
的Grid
一個控件。這需要12秒(!)在用戶粘貼來自Excel的122x161單元格後進行自我更新,這是非常慢的。解剖字符串需要0.1s,添加行和列需要1s,構建並插入TextBox
控件需要2s,剩餘的12s似乎花費在第一次繪製TextBox
控件。
我也試過DataGrid
,但它似乎並沒有很好地處理2D數組,它更喜歡使用反射爲屬性解析的1D對象數組。
現在我正在考慮只使用Canvas
並自己繪製數字,這似乎很瘋狂。有沒有簡單的方法來使用內置的WPF或Silverlight控件來完成這一任務,而不會對用戶造成痛苦的延遲?
編輯
因爲我已經確定TextBox
的罪魁禍首,因爲它是出奇的慢。下面是說明了這個問題的一些F#代碼(與TextBlock
和40X取代TextBox
更快,這仍然是數量比它慢應該的訂單,但可以接受在這種情況下):
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
您可以顯示當前的代碼和XAML以顯示您的網格嗎? – Rachel
@Rachel我已經發布了F#代碼,我已經說明了這個問題。 –