2

文字列が同一の場合、WPFフォームのテキストボックスでビューに印刷/バインド/投稿していないことが起こっています。たとえば、ランダムを使用して文字列にするバイト配列を生成すると、ビューに投稿されます。

ビューがバインドされているViewModelは次のとおりです。

   public class ViewModel : INotifyPropertyChanged
   {
      public StringBuilder Data
      {
         get { return _data; }
         set
         {
            _data = value;
            OnPropertyChanged("Data");
         }
      }

      private Service service = new Service();
      private StringBuilder _data;

      public ViewModel()
      {
         service.BytesArrived += ServiceOnBytesArrived;
         ThreadPool.QueueUserWorkItem(starupService);
      }

      private void starupService(object state)
      {
         service.Start();
      }

      private void ServiceOnBytesArrived(byte[] bytes)
      {
         var sBuilder = new StringBuilder();
         foreach (var b in bytes)
         {
            sBuilder.Append(b.ToString() + ", ");
         }

         Data = sBuilder;
      }

      public event PropertyChangedEventHandler PropertyChanged;

      protected virtual void OnPropertyChanged(string propertyName)
      {
         var handler = PropertyChanged;
         if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
      }
   }

これは、私のためにバイトを印刷するだけのサービスです(代わりにランダムが使用されている場合は正常に機能します:

   public class Service
   {
      public void Start()
      {
         var random = new Random(DateTime.Now.Minute);

       while (true)
       {
        //random.NextBytes(bytes);
        for (int i = 0; i < 10; i++)
        {
           bytes[i] = 0;
           Thread.Sleep(10);
        }
        //Thread.Sleep(100);
        BytesArrived(bytes);
       }
    }

  private byte[] bytes = new byte[10];
  public event Action<byte[]> BytesArrived;
}

私が使用している AppendText を使用するための依存関係プロパティは次のとおりです。

   public static class TextBoxAttachedBehaviors
   {
      #region AppendText Attached Property

      public static string GetAppendText(TextBox textBox)
      {
         return (string)textBox.GetValue(AppendTextProperty);
      }

      public static void SetAppendText(
         TextBox textBox, string value)
      {
         textBox.SetValue(AppendTextProperty, value);
      }

      public static readonly DependencyProperty AppendTextProperty =
         DependencyProperty.RegisterAttached(
            "AppendText",
            typeof(string),
            typeof(TextBoxAttachedBehaviors),
            new UIPropertyMetadata(null, OnAppendTextChanged));

      private static void OnAppendTextChanged(DependencyObject d,
                                              DependencyPropertyChangedEventArgs e)
      {
         if (e.NewValue == null)
            return;
         TextBox textBox = d as TextBox;
         textBox.AppendText(e.NewValue.ToString());
      }

      #endregion
   }

XAML:

<TextBox attachedBehaviors:TextBoxAttachedBehaviors.AppendText="{Binding TextBoxAppend}"/>

ReSharper をお持ちの場合は、名前空間を置き換えることを提案します。たとえばattachedBehaviors:、クラスへのリンクを実際に添付されたビヘイビア (私の場合はxmlns:attachedBehaviors="clr-namespace:Support.NetworkMonitor.AttachedBehaviors".

4

2 に答える 2

1

DependencyProperties は、通知を起動する前に古い値と新しい値を比較し、実際に違いがある場合にのみ起動します。解決策は簡単です。次のように、文字列を設定する前に AppendText を null に設定します。

  public StringBuilder Data
  {
     get { return _data; }
     set
     {
        _data = null;
        OnPropertyChanged("Data");
        _data = value;
        OnPropertyChanged("Data");
     }
  }
于 2012-11-29T18:18:06.710 に答える
0

私が書いた実用的なアプリケーションからこれを見つけました...おそらくこれが役立ちます。

    Public Class TextBoxLog
    Inherits Freezable
    Implements WPFGlue.Framework.IStickyComponent

    Private _AppendTextDelegate As Action(Of String)
    Private _ScrollToEndDelegate As Action
    Private _ResetDelegate As Action

    Public Shared ReadOnly LogProperty As DependencyProperty = DependencyProperty.RegisterAttached("Log", GetType(TextBoxLog), GetType(TextBoxLog), New PropertyMetadata(AddressOf WPFGlue.Framework.StickyComponentManager.OnStickyComponentChanged))
    Public Shared Function GetLog(ByVal d As DependencyObject) As TextBoxLog
        Return d.GetValue(LogProperty)
    End Function
    Public Shared Sub SetLog(ByVal d As DependencyObject, ByVal value As TextBoxLog)
        d.SetValue(LogProperty, value)
    End Sub


    Public Shared ReadOnly LogMessageProperty As DependencyProperty = DependencyProperty.Register("LogMessage", GetType(String), GetType(TextBoxLog), New PropertyMetadata(AddressOf OnLogMessageChanged))
    Public Property LogMessage As String
        Get
            Return GetValue(LogMessageProperty)
        End Get
        Set(ByVal value As String)
            SetValue(LogMessageProperty, value)
        End Set
    End Property
    Private Shared Sub OnLogMessageChanged(ByVal d As TextBoxLog, ByVal e As DependencyPropertyChangedEventArgs)
        If e.NewValue IsNot Nothing Then
            d.WriteLine(e.NewValue)
        End If
    End Sub

    Protected Overridable Sub Attach(base As Object)
        If Not TypeOf base Is System.Windows.Controls.Primitives.TextBoxBase Then
            Throw New ArgumentException("Can only be attached to elements of type TextBoxBase")
        End If
        Dim tb As System.Windows.Controls.Primitives.TextBoxBase = base
        _AppendTextDelegate = AddressOf tb.AppendText
        _ScrollToEndDelegate = AddressOf tb.ScrollToEnd
        _ResetDelegate = AddressOf Me.Reset
    End Sub

    Protected Overridable Sub Detach(ByVal base As Object)
        _AppendTextDelegate = Nothing
        _ScrollToEndDelegate = Nothing
        _ResetDelegate = Nothing
    End Sub

    Private Sub Reset()
        SetCurrentValue(LogMessageProperty, Nothing)
    End Sub

    Protected Overrides Function CreateInstanceCore() As System.Windows.Freezable
        Return New TextBoxLog
    End Function

    Public Overridable Sub Write(message As String)
        If _AppendTextDelegate IsNot Nothing Then
            _AppendTextDelegate.Invoke(message)
            _ScrollToEndDelegate.Invoke()
            '               Me.Dispatcher.Invoke(_ResetDelegate, Windows.Threading.DispatcherPriority.Background)
        End If
    End Sub

    Public Overridable Sub WriteLine(message As String)
        If _AppendTextDelegate IsNot Nothing Then
            _AppendTextDelegate.Invoke(message)
            _AppendTextDelegate.Invoke(vbNewLine)
            _ScrollToEndDelegate.Invoke()
            '                Me.Dispatcher.Invoke(_ResetDelegate, Windows.Threading.DispatcherPriority.Background)
        End If
    End Sub

    Public ReadOnly Property Mode As Framework.AttachMode Implements Framework.IStickyComponent.Mode
        Get
            Return Framework.AttachMode.Immediate
        End Get
    End Property

    Public Sub OnAttach(base As Object, e As System.EventArgs) Implements Framework.IStickyComponent.OnAttach
        If e Is System.EventArgs.Empty Then
            Attach(base)
        End If
    End Sub

    Public Sub OnDetach(base As Object, e As System.EventArgs) Implements Framework.IStickyComponent.OnDetach
        If e Is System.EventArgs.Empty Then
            Detach(base)
        End If
    End Sub
End Class

この投稿では、Log 添付プロパティが設定されたときに OnAttach が呼び出され、設定が解除されたとき、またはアンロード時に OnDetach が呼び出されると想定できます。

于 2012-11-30T18:58:06.813 に答える