1

我想要做的很簡單,當TextBox具有焦點時顯示一種格式,而當文本框沒有焦點時顯示另一種格式。在我的情況下,我將一個數字四捨五入爲3位數字,但不顯示焦點時顯示實際的整數,以便進行編輯。當使用MultiBinding聚焦時TextBox的不同格式不會更新源

我有一個相當簡單的解決方案,使用多重綁定,我覺得我幾乎在那裏。一切都按預期工作,在即時窗口中沒有錯誤,但綁定不會更新源。

我正在使用此樣式來傳遞我的綁定以及TextBox是否具有焦點到轉換器。

<Style x:Key="RoundedTextBox" TargetType="{x:Type ContentControl}"> 
    <Setter Property="Focusable" Value="False"/> 
    <Setter Property="ContentTemplate"> 
     <Setter.Value> 
      <DataTemplate> 
       <TextBox x:Name="TB" TextAlignment="Right" DataContext="{TemplateBinding Content}"> 
        <TextBox.Text> 
         <MultiBinding Converter="{StaticResource DecRounder}" UpdateSourceTrigger="PropertyChanged"> 
          <MultiBinding.Bindings> 
           <Binding ElementName="TB" Path="DataContext" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" BindsDirectlyToSource="True" /> 
           <Binding ElementName="TB" Path="IsFocused" Mode="OneWay" /> 
          </MultiBinding.Bindings> 
         </MultiBinding> 
        </TextBox.Text> 
       </TextBox> 
      </DataTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

實例:

<ContentControl Style="{StaticResource RoundedTextBox}" 
       Content="{Binding Path=Model.SomeNumber}" /> 

和多值轉換器在這裏。

public class DecimalRoundingConverter : IMultiValueConverter 
{ 

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 

     if (values.Length != 2) 
      throw new Exception("Invalid number of values for DecimalRoundingConverter!"); 

     if (values[0] is string) 
      return values[0]; 

     if (values[0] != null && !(values[0] is decimal)) 
      throw new Exception("Invalid type for first value used with DecimalRoundingConverter!"); 
     if (!(values[1] is bool)) 
      throw new Exception("Invalid type for second value used with DecimalRoundingConverter!"); 
     if (targetType != typeof(string)) 
      throw new Exception("Invalid target type used with DecimalRoundingConverter!"); 

     if (values[0] == null) 
      return null; 

     decimal number = (decimal)values[0]; 

     bool isFocused; 
     if (values[1] == null) 
      isFocused = true; 
     else if (values[1] is bool) 
      isFocused = (bool)values[1]; 
     else 
      if (!bool.TryParse((string)values[1], out isFocused)) 
       throw new Exception("Invalid converter parameter used with DecimalRoundingConverter!"); 

     return string.Format(isFocused ? "{0:.#############################}" : "{0:.###}", number); 

    } 

    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 

     decimal d; 
     var ret = new object[2]; 

     if (value == null) 
      ret[0] = null; 
     else if (decimal.TryParse((string)value, out d)) 
      ret[0] = d; 
     else 
      ret[0] = value; 

     ret[1] = Binding.DoNothing; 

     return ret; 

    } 

} 

回答

0

對於它的價值,我來源於此CodeProject article的解決方案。關鍵是在樣式中使用觸發器來切換內容模板。提供的例子並不完美,但這是一次很好的學習經歷。

此方法的唯一缺點是ContentTemplates和Style必須在UserControl中定義,因爲ContentTemplates直接指向TextBox事件處理程序。這是因爲對TextBox的引用必須傳遞給後面的代碼。當您嘗試覆蓋樣式時,您將失去切換ContentTemplate的觸發器。

這個缺點對我來說很好,因爲我綁定到重要屬性的應用程序設置,比如ContentStringFormat。

編輯

下面是完整的XAML一個更好的方法。我寫了一個corresponding article on my blog

<ControlTemplate x:Key="EditableDecimalTemplate" TargetType="{x:Type ContentControl}"> 
    <ContentPresenter Name="contentHolder" 
          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
          RecognizesAccessKey="True" 
          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"> 
     <ContentPresenter.Content> 
      <Grid Margin="0"> 
       <Border Name="nonFocusedBorder" 
         Grid.ZIndex="3" IsHitTestVisible="False" 
         BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
         Background="{TemplateBinding Background}" 
         /> 
       <TextBox Name="editTextBox" 
          Grid.ZIndex="1" Opacity="0" 
          Margin="0" Padding="{TemplateBinding Padding}" 
          HorizontalAlignment="Stretch" VerticalAlignment="Center" 
          TextAlignment="Right" 
          Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay}" 
          BorderThickness="{TemplateBinding BorderThickness}" 
          /> 
       <Border BorderBrush="{x:Null}" Height="{Binding ElementName=editTextBox, Path=ActualHeight}" Margin="0,0,3,0" 
         Padding="{TemplateBinding BorderThickness}"> 
        <TextBlock Name="displayTextBlock" 
           Grid.ZIndex="2" IsHitTestVisible="False" 
           VerticalAlignment="Center" HorizontalAlignment="Stretch" 
           Margin="{TemplateBinding Padding}" 
           TextAlignment="Right" 
           Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, StringFormat={}{0:#.###;-#.###;0}, Mode=OneWay}" 
           /> 
       </Border> 
       <Border/> 
      </Grid> 
     </ContentPresenter.Content> 
    </ContentPresenter> 
    <ControlTemplate.Triggers> 
     <Trigger SourceName="editTextBox" Property="IsKeyboardFocused" Value="True"> 
      <Setter TargetName="displayTextBlock" Property="Opacity" Value="0" /> 
      <Setter TargetName="editTextBox" Property="Opacity" Value="1" /> 
      <Setter TargetName="nonFocusedBorder" Property="Visibility" Value="Collapsed"/> 
     </Trigger> 
     <Trigger Property="BorderThickness" Value="0"> 
      <Setter TargetName="editTextBox" Property="BorderThickness" Value="1" /> 
      <Setter TargetName="nonFocusedBorder" Property="BorderThickness" Value="1" /> 
      <Setter TargetName="nonFocusedBorder" Property="BorderBrush" Value="Transparent" /> 
     </Trigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 

<Style x:Key="EditableDecimalLabel" TargetType="{x:Type Label}"> 
    <Setter Property="Template" Value="{StaticResource EditableDecimalTemplate}" /> 
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 
    <Setter Property="VerticalContentAlignment" Value="Stretch"/> 
    <Setter Property="Padding" Value="4" /> 
    <Setter Property="FontFamily" Value="Consolas, Lucida Console, Courier New"/> 
    <Setter Property="TextElement.FontSize" Value="13" /> 
    <Setter Property="SnapsToDevicePixels" Value="True"/> 
    <Setter Property="BorderThickness" Value="1" /> 
    <Style.Triggers> 
     <Trigger Property="IsMouseOver" Value="True"> 
      <Setter Property="BorderBrush" Value="#B5CFFF"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

而且樣品用量:

<Label Name="TestControl" 
     Width="120" 
     Content="{Binding Path=MyNumber, Mode=TwoWay}" 
     Style="{StaticResource EditableDecimalLabel}" 
     /> 
相關問題