2012-02-03 85 views
8

我有一個TextBox樣式,如果該框未聚焦,則格式化數字,但會在編輯時留下未格式化的數字。我可以在不知道綁定本身的情況下更改DataTrigger中綁定的屬性嗎?

這是我想要的多個文本框的樣式,但它們都包含不同的文本綁定。常規文本設置器和觸發文本設置器之間唯一的區別在於觸發器在綁定中有StringFormat=N2

有沒有一種方法可以使這種風格是通用的,比如只更改DataTrigger中綁定的StringFormat屬性?

<TextBox> 
    <TextBox.Style> 
     <Style TargetType="{x:Type TextBox}"> 
       <Setter Property="Text" Value="{Binding SomeValue, StringFormat=N2, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
      <Style.Triggers> 
       <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
        <Setter Property="Text" Value="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </TextBox.Style> 
</TextBox> 
+0

我認爲不可能在應用後改變綁定的任何屬性。至少當我嘗試更改現有綁定的StringFormat屬性時,我得到一個InvalidOperationException,說'綁定在使用後無法更改'。對我來說,似乎沒有辦法在每次焦點更改時都創建一個新綁定。 – Clemens 2012-02-03 14:18:01

+0

再次考慮了這個問題,並考慮了某種附加的'Data'屬性解決方案,其中屬性更改處理程序將附加GotFocus/LostFocus處理程序等。最後,我希望有一個派生的TextBox,其中包含屬性'Data'和'StringFormat ',它將根據它們的值和當前焦點狀態來設置「文本」屬性。 – Clemens 2012-02-04 08:53:51

回答

0

我想知道,如果你可以,也許對編輯的附加屬性來保存格式化值(只綁定到一個的StringFormat真實編輯值使用),然後在你的聚焦觸發你可以的將編輯值設置爲此屬性。

這將導致一個循環綁定,雖然編輯沒有焦點時,不知道WPF如何在這種情況下作出反應。

0

很遺憾,這是(據我所知)不可能。一種可能的解決方法是以編程方式即時創建這種樣式,這可以封裝在將路徑作爲構造器參數的MarkupExtension中。

2

是有一種方法可以使此風格具有通用性,例如僅更改DataTrigger中綁定的StringFormat屬性 ?

繼承Style和新的XAML將成爲這樣的:

<TextBox> 
    <TextBox.Style> 
     <local:FlyingStyle Binding="{Binding ElementName=This, Path=SomeValue}" StringFormat="F2" /> 
    </TextBox.Style> 
</TextBox> 

這裏的類...

public class FlyingStyle : Style 
{ 
    public FlyingStyle() 
     : base(typeof(TextBox)) 
    { } 

    string _stringFormat; 
    public string StringFormat 
    { 
     get { return _stringFormat; } 
     set 
     { 
      _stringFormat = value; 
      CheckInitialize(); 
     } 
    } 
    Binding _binding; 
    public Binding Binding 
    { 
     get { return _binding; } 
     set 
     { 
      _binding = value; 
      CheckInitialize(); 
     } 
    } 
    void CheckInitialize() 
    { 
     if (StringFormat == null || Binding == null) { return; }// need both 

     Setters.Add(CreateSetter(Binding, StringFormat)); 

     var trigger = new Trigger 
     { 
      Property = UIElement.IsKeyboardFocusWithinProperty, 
      Value = true, 
     }; 
     trigger.Setters.Add(CreateSetter(Binding)); 
     Triggers.Add(trigger); 
    } 

    /// <summary>Creates the common <see cref="Setter"/>.</summary> 
    static Setter CreateSetter(Binding binding, string stringFormat = null) 
    { 
     // must create a copy, because same binding ref but diff StringFormats 
     var bindingCopy = new Binding 
     { 
      // these could be copies as well 
      UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, 
      ValidatesOnDataErrors = true, 
      Mode = BindingMode.TwoWay, 
      Path = binding.Path, 

      AsyncState = binding.AsyncState, 
      BindingGroupName = binding.BindingGroupName, 
      BindsDirectlyToSource = binding.BindsDirectlyToSource, 
      Converter = binding.Converter, 
      ConverterCulture = binding.ConverterCulture, 
      ConverterParameter = binding.ConverterParameter, 
      ElementName = binding.ElementName, 
      FallbackValue = binding.FallbackValue, 
      IsAsync = binding.IsAsync, 
      NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated, 
      NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated, 
      NotifyOnValidationError = binding.NotifyOnValidationError, 
      //StringFormat = set below... 
      TargetNullValue = binding.TargetNullValue, 
      UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter, 
      ValidatesOnExceptions = binding.ValidatesOnExceptions, 
      XPath = binding.XPath, 
      //ValidationRules = binding.ValidationRules 
     }; 
     // mutex ElementName, so modify if needed 
     // Source = binding.Source, 
     // RelativeSource = binding.RelativeSource, 

     if (stringFormat != null) 
     { 
      bindingCopy.StringFormat = stringFormat; 
     } 
     return new Setter(TextBox.TextProperty, bindingCopy); 
    } 
} 

請注意,我的測試是

  • 通用主窗口
  • 個IMPL INotifyPropertyChanged的
  • SomeValue INPC財產
  • 的DataContext =這個
  • X:名稱=這
+0

我寧願將我的風格留在XAML中,我可以輕鬆訪問它以對其進行更改。這看起來像一個噩夢:) – Rachel 2012-02-11 15:41:58

+0

'這是我想要的多個文本框的樣式,但它們都包含不同的文本綁定'使它聽起來像它值得C#。無論如何,David的答案中的鏈接提出了幾乎相同的算法。 – 2012-02-13 14:59:40

+0

對於工作版本+1,但我更喜歡David鏈接中顯示的附加屬性,因爲它允許我將我的樣式的其餘部分保留在XAML中 – Rachel 2012-02-13 18:24:41

2

我試圖解決這個結束了一個自定義的控制以及多結合,這兩個地方的如上所述。

這讓我用類似這樣的標記:

< CustomTextBox值=「{綁定值」}格式=「N2」 />

我嘗試後我的代碼,但我不斷收到一個錯誤關於「未正確格式化爲代碼的代碼」。

相關問題