0

私は、線やその他のジオメトリのカスタム描画に使用される「パネル」から派生した種類のキャンバスを、すべてVBコードから持っています。私はこのアプローチを本から得ましたが、それが最良のアプローチであるかどうかはわかりません。描画部分はこれまでのところうまくいきます。

しかし、私が必要とするのは、ユーザーが編集できるテキストを含むコントロールにテキスト ボックス コントロールを配置することです。テキストボックスは、動的に決定され、後で削除される座標に配置する必要があります。おそらく他のコントロールがそのように処理されるでしょう。

次のコードは何もしません。

    tb = New TextBox()
    tb.Text = "How now brown cow?"
    tb.BorderThickness = New Thickness(3)
    tb.BorderBrush = Brushes.CadetBlue
    drawingSurface.Children.Add(tb)

これは私のDrawingCanvasの定義です:

    Public Class DrawingCanvas
   Inherits Panel

    Private visuals As New List(Of Visual)()
    Private hits As New List(Of DrawingVisual)()

   Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
      Return visuals(index)
   End Function
   Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
      Get
         Return visuals.Count
      End Get
   End Property

   Public Sub AddVisual(ByVal visual As Visual)
      visuals.Add(visual)
        MyBase.AddVisualChild(visual)
      MyBase.AddLogicalChild(visual)
   End Sub

   Public Sub DeleteVisual(ByVal visual As Visual)
      visuals.Remove(visual)
        MyBase.RemoveVisualChild(visual)
      MyBase.RemoveLogicalChild(visual)
   End Sub

   Public Function GetVisual(ByVal point As Point) As DrawingVisual
      Dim hitResult As HitTestResult = VisualTreeHelper.HitTest(Me, point)
      Return TryCast(hitResult.VisualHit, DrawingVisual)
   End Function

    Public Function GetVisuals(ByVal region As Geometry) As List(Of DrawingVisual)
        hits.Clear()
        Dim parameters As New GeometryHitTestParameters(region)
        Dim callback As New HitTestResultCallback(AddressOf Me.HitTestCallback)
        VisualTreeHelper.HitTest(Me, Nothing, callback, parameters)
        Return hits
    End Function

   Private Function HitTestCallback(ByVal result As HitTestResult) As HitTestResultBehavior
      Dim geometryResult As GeometryHitTestResult = CType(result, GeometryHitTestResult)
      Dim visual As DrawingVisual = TryCast(result.VisualHit, DrawingVisual)
      If visual IsNot Nothing AndAlso geometryResult.IntersectionDetail = IntersectionDetail.FullyInside Then
            hits.Add(visual)
            MsgBox("Ouch")
      End If
      Return HitTestResultBehavior.Continue
   End Function
End Class

ここに XAML があります。何かが表示されるかどうかを確認するためだけに、DrawingCanvas にテキスト ボックスを追加しました。何もしませんでした。実際、これは XAML ではなくコードで行いたいと考えています。動的に隠したり移動したりできると思いました。

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Music"
    Title="MainWindow" Height="539" Width="892">
    <DockPanel>
        <Menu DockPanel.Dock="Top" Name="MainMenu" VerticalAlignment="Top" Height="25">
            <MenuItem Name="File" Header="File">
                <MenuItem Name="Open" Header="Bla bla..."/>
            </MenuItem>
        </Menu>
        <local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
            <TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
        </local:DrawingCanvas>
    </DockPanel>
</Window>

ヌービーを助けてくれてありがとう。解決策は私にとって非常に役立ちます。これは Windows フォームでは簡単でしたが、WPF の描画速度が必要です。

4

3 に答える 3

0

あなたが探しているものにより近いかもしれない別の答えを追加します。これは Canvas から継承するクラスで、コメントで言うのと同じ方法で描画できるようになります。

また、作成時にランダムな場所にテキストボックスを作成します。

Public Class DrawingCanvas
    Inherits Canvas
    Public RandomTextBox As New TextBox
    Protected Overrides Sub OnRender(dc As System.Windows.Media.DrawingContext)
        Dim brush As Brush = Brushes.Black
        Dim drawingPen As Pen = New Pen(Brushes.Green, 3)
        dc.DrawRectangle(brush, drawingPen, New Rect(5, 5, Me.ActualWidth - 5, Me.ActualHeight - 5))
        RandomTextBox.Text = "Herpdiderp"
        If Not Me.Children.Contains(RandomTextBox) Then
            Dim r As New Random()
            RandomTextBox.Height = 23
            RandomTextBox.Width = 100
            Me.SetTop(RandomTextBox, r.Next(0, Me.ActualHeight - RandomTextBox.Height))
            Me.SetLeft(RandomTextBox, r.Next(0, Me.ActualWidth - RandomTextBox.Width))
            Me.Children.Add(RandomTextBox)
        End If
    End Sub
End Class
于 2013-04-30T09:04:21.693 に答える
0

あなたはここで少しずれていると思います。WPF には Canvas というコントロールがあります。あなた自身の「DrawingCanvas」の代わりにそれを使用することをお勧めします。:( (何らかの理由でコードブロックを作成できないので、誰かが編集できると嬉しいです)

とにかく、

<local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
   <TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
</local:DrawingCanvas>

になる:

 <Canvas x:Name="drawingSurface">

 </Canvas>

そして、テキストボックスを追加するには、現在のコードと同じようにします:

Dim tb as New TextBox 
drawingSurface.Children.Add(tb)

これにより、必要なものが得られるはずです。

キャンバスに四角形を追加するコードを次に示します。

Private Sub DrawBackground()
    Dim Rect As New Rectangle()
    Rect.Height = 50
    Rect.Width = 50
    Rect.Fill = Brushes.Cornsilk
    drawingSurface.SetTop(Rect, 30)
    drawingSurface.SetLeft(Rect, 100)
    drawingSurface.Children.Add(Rect)
End Sub
于 2013-04-29T07:17:56.223 に答える
0

これは完全な答えではありません。#WozzeC さん、キャンバスの使い方は正しかった - ほとんど。

これを xaml だけで解決できました。最終的には vb.net で解決したいと考えています。

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
    <DockPanel HorizontalAlignment="Stretch" Name="DockPanel1" VerticalAlignment="Stretch" >
        <Menu Height="23" DockPanel.Dock="Top"  Name="Menu1" VerticalAlignment="Top" />
        <Canvas Name="Canvas1" Background="Aquamarine">
            <TextBox Canvas.Left="118" HorizontalScrollBarVisibility="Disabled" Canvas.Top="81" AcceptsReturn="True"  Height="auto" Name="TextBox1" Width="68" Text="Herpdiderp" BorderThickness="0" Background="Aquamarine" />
        </Canvas>
    </DockPanel>
</Grid>

そして、必要に応じてテキストを展開するコードを次に示します。私はそれがほとんど完全にクールだと思います。実際にフォームに入力しているかのように、右と下の両方に展開します。右側に少し足しすぎましたが、このバージョンでは背景色が同じなので見えません。

これを右に展開するイベント コードを次に示します。

    Imports System.Globalization
Class MainWindow
Private Sub TextBox1_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs) Handles TextBox1.TextChanged
    Dim ft As New FormattedText(TextBox1.Text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, New Typeface("Verdana"), 16, Brushes.Black)
    TextBox1.Width = ft.Width
End Sub
End Class

既存のソリューションでこれを試しましたが、テキストボックスが表示されませ。DrawingCanvas をプレーンなキャンバスにし、DrawingCanvas を参照するすべてのコードをコメントアウトしました。そして、テキストボックス表示されます。問題はこれです: Canvas から派生した DrawingCanvas の機能が必要です。しかし、基本クラスのメソッドは Protected であるため、アクセスできません。私が知らない別の方法がない限り、派生クラスでのみ使用できます。

これを解決する方法についてのアイデアはありますか?

于 2013-05-05T20:26:14.423 に答える