0

我利用綁定到數據對象的DataGridTextColumn在應用程序中顯示各種測量。我試圖實現一項功能,可以讓測量結果以不同的單位顯示,並且認爲綁定中的Converter可能是我的最佳選擇。轉換器從DataGrid而不是綁定對象獲取值?

這適用於大多數應用程序,但我在DataGrid中有另一個字段,用戶可以在其中編輯該字段的值。在這種情況下,我有一個雙向數據綁定,將用戶的輸入值(假設爲華氏度)轉換爲數據對象的默認單位(攝氏度)。

我期望轉換器從數據對象中檢索Celcius中的值,進行轉換,然後將此值(華氏度)發送到DataGridTextColumn。但是,在設置數據對象的值並通知PropertyChanged後,該屬性的'get'方法未被調用。相反,Convert似乎是從DataGridTextColumn獲取用戶輸入值(華氏溫度)。

這是正常的行爲,如果是這樣,有沒有辦法強制轉換始終返回數據對象的值?

幾個片段,以幫助:

<Window.Resources> 
    <myProject:ConvertMetricValuesToEnglish x:Key="ValueMToE" /> 
</Window.Resources> 
. 
. 
. 
<DataGridTextColumn x:Name="maxCol" Header="Maximum" Width="100"> 
    <DataGridTextColumn.Binding> 
     <MultiBinding Mode="TwoWay" StringFormat='0.#####' Converter="{StaticResource ValueMToE}" > 
      <Binding Path="UserMax" Mode="TwoWay" /> 
      <Binding Path="Unit" Mode="OneWay" /> 
     </MultiBinding> 
    </DataGridTextColumn.Binding> 
</DataGridTextColumn> 

轉換方法:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
{ 
    if (values.Length != 2) 
    { 
     return null; 
    } 
    if (values[0].GetType() != typeof(double) || values[1].GetType() != typeof(string)) 
    { 
     return values[0]; 
    } 
    double d = (double)values[0]; 
    string s = (string)values[1]; 

    return ConvertValueToEnglish(d, s); 
} 

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
{ 
    return new object[] { StringToDouble((string)value), Binding.DoNothing }; 
} 

我做'ConvertBack的轉換在二傳手,因爲在ConvertBack現有的有限信息:

private double? _userMax; 
    public double UserMax 
    { 
     get 
     { 
      if (_userMax == null) 
      { 
       _userMax = Max; 
      } 

      return (double)_userMax; 
     } 
     set 
     { 
      if (Metric) 
      { 
       if (value == _userMax) 
       { 
        return; 
       } 
       _userMax = value; 
      } 
      else 
      { 
       double num = ConvertValueToMetric(value, _unit); 
       if (num == _userMax) 
       { 
        return; 
       } 
       _userMax = num; 
      } 
      OnPropertyChanged("UserMax"); 
     } 
    } 

編輯:下面是一個示例項目的鏈接證明了這個問題。左列是用戶可編輯的,並且表示用戶看到/編輯的數據。右列顯示用戶進行更改時實際存儲的基礎值(此值不應更改)。

如果您修改左列中的值,並且「Tab」超出範圍或在同一行中選擇不同的列,則可以看到您輸入的值發生了變化。但是當這一行失去焦點時它會改變。通過設置斷點,您可以看到當單元本身失去焦點時,將使用DependencyProperty.UnsetValue的方法調用Convert方法,然後調用Unit的get方法,然後再次使用DataGrid中的值轉換Convert方法。

TempConverter.zip

+0

我把你的代碼放在一起,這是一個有點混亂。它不按原樣編譯。您有一個未定義的ConvertValueToMetric,_unit,Metric,Max,ConvertValueToEnglish和StringToDouble屬性/方法。我可以獲得更好的代碼示例嗎?或者幫我把這些物品放在一起? – paqogomez

+0

@paqogomez - 我上傳了一個示例項目來演示我遇到的問題。 – aswanson

+0

我正在運行該項目。您希望有正確的欄目反映左欄中的更改? – paqogomez

回答

1

我能制定出我自己的解決方案。問題是源數據對象沒有被更新,直到DataGrid中的整行失去焦點。爲了解決這個問題,我將一個TextBox作爲ControlTemplate應用於單元格,並在TextBox失去焦點時設置一個觸發UpdateSource的事件。

XAML:

<DataGridTextColumn x:Name="maxCol" Header="Maximum" Width="100"> 
    <DataGridTextColumn.CellStyle> 
     <Style TargetType="DataGridCell"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate> 
         <TextBox LostFocus="TextBlock_LostFocus"> 
          <TextBox.Text> 
           <MultiBinding StringFormat='0.#####' Converter="{StaticResource ValueMToE}" UpdateSourceTrigger="Explicit"> 
            <Binding Path="UserMax" Mode="TwoWay" /> 
            <Binding Path="Unit" Mode="OneWay" /> 
           </MultiBinding> 
          </TextBox.Text> 
         </TextBox> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </DataGridTextColumn.CellStyle> 
</DataGridTextColumn> 

事件處理程序:

private void TextBlock_LostFocus(object sender, RoutedEventArgs e) 
{ 
    TextBox b = sender as TextBox; 
    if (b == null) 
    { 
     return; 
    } 
    MultiBindingExpression mb = BindingOperations.GetMultiBindingExpression(b, TextBox.TextProperty); 
    mb.UpdateSource(); 
} 
相關問題