私がやりたいことは簡単です。TextBox にフォーカスがある場合は 1 つの書式を表示し、フォーカスがない場合は別の書式を表示します。私の場合、フォーカスされていないときは数値を 3 桁に丸めていますが、編集のためにフォーカスされているときは実際の数値全体を表示しています。
マルチバインディングを使用したかなり単純なソリューションがあり、ほとんどそこにいるような気がします。すべてが期待どおりに機能し、即時ウィンドウにエラーはありませんが、バインディングはソースを更新しません。
このスタイルを使用してバインディングを渡し、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;
}
}