2011-07-08 13 views
0

我有一個GUI元素,應該以毫米爲單位顯示特定的大小。
爲此,我有一個(全局)靜態類PPMM(=每毫米像素)與double? Factorevent FactorChanged,都是靜態的。 Factor的設置程序調用FactorChanged事件處理程序。
GUI中的元素是UserControls並掛鉤(在構造函數中)到FactorChanged事件來更新它們的像素大小或ScaleTransforms。如何調整靜態事件上的WPF元素?

佈局GUI時,我不想爲每個以毫米爲單位大小的對象創建UserControl。
相反,我想使用的東西的方式

<elem Margin="0, {?:getPixelsFromMillimeters(
    desiredSize:{x:Const 20mm}, 
    fallback:{x:Const 80px})}" /> 

毫米大小和後備像素大小應該是綁定。

我考慮結合Factor並使用IValueConverter具有所需毫米尺寸在轉換器的parameter。但後來我無法綁定到一個變量mm大小的值。

我可以綁定到毫米大小並使用轉換器,但隨後更改Factor不會更新該度量。

我也沒能創造一個靜態類(GetValueSetValue不可有)一個DependencyProperty,但是這將是一個不同的SO問題...

什麼是正確的方式來實現我在做什麼?

有沒有我沒有答案的細節?如果是,請留下評論。

+0

爲什麼「改變因子不會更新度量」?如果您的綁定將在屬性更改時更新(「Factor的setter調用FactorChanged事件處理程序。」),它必須更改。我認爲轉換器+綁定可以正確解決您的問題。 – stukselbax

+0

@stukselbax我試圖通過一個依賴屬性,但看起來不工作在靜態類。當前實現:Factor =常用靜態屬性,FactorChanged =自定義靜態事件處理程序 –

+0

對於您的情況,「static」是否如此重要?想想看... – stukselbax

回答

0

我想出了一個工作從stukselbax的評論回答自己...

簡而言之:一些WPF大小或其他措施財產multibinds到靜態的DependencyProperty 因子和一些靜態雙打作爲參數(大小以mm爲單位,後退大小以像素爲單位)通過IMultiValueConverter。靜態因子來自單身人士。在其他類可以訂閱的單例中還有一個附加事件FactorChanged

創建一個類來作爲單身實例:

public class PPMMSingleton : DependencyObject 
{ 
    public double? Factor 
    { 
     get { return (double?)GetValue(FactorProperty); } 
     set { SetValue(FactorProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Factor. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty FactorProperty = 
     DependencyProperty.Register("Factor", typeof(double?), typeof(PPMMSingleton), 
      new FrameworkPropertyMetadata(null, 
       FrameworkPropertyMetadataOptions.AffectsMeasure | 
       FrameworkPropertyMetadataOptions.AffectsRender | 
       FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | 
       FrameworkPropertyMetadataOptions.Inherits, 
       new PropertyChangedCallback(OnFactorChanged), 
       new CoerceValueCallback(CoerceFactor))); 

    private static object CoerceFactor(DependencyObject element, object value) 
    { 
     return value; 
    } 

    public static void OnFactorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
    { 
     PPMMSingleton ppmm = (PPMMSingleton)sender; 

     ppmmEventArgs e = 
      new ppmmEventArgs(
       (double?)args.OldValue, 
       (double?)args.NewValue); 
     ppmm.OnFactorChanged(e); 
    } 

    private void OnFactorChanged(ppmmEventArgs e) 
    { 
     if (FactorChanged != null) 
      FactorChanged(e); 
    } 

    public event ppmmEventHandler FactorChanged; 
} 

爲FactorChanged創建委託和EventArgs的:

public delegate void ppmmEventHandler(ppmmEventArgs e); 

public class ppmmEventArgs : EventArgs 
{ 
    public ppmmEventArgs(double? oldFactor, double? newFactor) 
    { 
     OldFactor = oldFactor; 
     NewFactor = newFactor; 
    } 

    public double? OldFactor { get; private set; } 
    public double? NewFactor { get; private set; } 
} 

創建一個靜態類主辦這一單:

public static class PPMM 
{ 
    public static double? Factor 
    { 
     get { return Singleton.Factor; } 
     set 
     { 
      Singleton.Factor = value; 
     } 
    } 

    private static PPMMSingleton _singleton = null; 
    public static PPMMSingleton Singleton 
    { 
     get 
     { 
      if (_singleton == null) 
       _singleton = new PPMMSingleton(); 
      return _singleton; 
     } 
    } 

    public static event ppmmEventHandler FactorChanged 
    { 
     add { Singleton.FactorChanged += value; } 
     remove { Singleton.FactorChanged -= value; } 
    } 
} 

創建一個IMultiValueConverter,其中包含因子,以mm爲單位的大小和可選的大小以像素作爲後備:

public class FactorAndMillimeterToPixelConverter : IMultiValueConverter 
{ 
    #region IMultiValueConverter Member 

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if ((values.Length < 2) 
      || !(values[0] is double?)) 
      return Binding.DoNothing; 

     double? factor = (double?)values[0]; 

     switch(values.Length) 
     { 
      case 2: 
       if(!(values[1] is double)) 
        return Binding.DoNothing; 
       // values[0]: Factor, values[1]: SizeMM 
       // if Factor is null, no fallback provided -> donothing 
       if (!factor.HasValue) 
        return Binding.DoNothing; 
       // else return calculated width 
       return factor.Value * (double)values[1]; 

      case 3: 
       if (!(values[1] is double) || !(values[2] is double)) 
        return Binding.DoNothing; 
       // values[0]: Factor, values[1]: SizeMM, values[2]: SizePixelsFallback 
       // if Factor is null, but fallback provided -> return fallback 
       if (!factor.HasValue) 
        return (double)values[2]; 
       // else return calculated width 
       return factor.Value * (double)values[1]; 

      default: 
       // value.Length > 3 
       return Binding.DoNothing; 
     } 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

把資源用在你的XAML轉換器:

 <mynamespace:FactorAndMillimeterToPixelConverter x:Key="fm2pconv" /> 

多路捆綁到靜態因子依賴屬性,並在毫米的尺寸和像素回退大小(包括爲靜態雙打)在XAML:

<Border> 
     <Border.Width> 
      <MultiBinding Converter="{StaticResource fm2pconv}"> 
       <MultiBinding.Bindings> 
        <Binding Path="Factor" Source="{x:Static tc:PPMM.Singleton}" /> 
        <Binding> 
         <Binding.Source> 
          <sys:Double>50</sys:Double> 
         </Binding.Source> 
        </Binding> 
        <Binding> 
         <Binding.Source> 
          <sys:Double>400</sys:Double> 
         </Binding.Source> 
        </Binding> 
       </MultiBinding.Bindings> 
      </MultiBinding> 
     </Border.Width> 
     <TextBlock 
      Text="Wenn Factor gesetzt ist, ist dieser Kasten 50mm breit. Ansonsten ist er 400px breit. Seine Width wird beeinflusst." 
      TextWrapping="WrapWithOverflow" 
      > 
     </TextBlock> 
    </Border> 

人們還可以在毫米大小結合到依賴屬性(假設正確DataContext設置):

 <Border.Width> 
      <MultiBinding Converter="{StaticResource fm2pconv}"> 
       <MultiBinding.Bindings> 
        <Binding Path="Factor" Source="{x:Static tc:PPMM.Singleton}" /> 
        <Binding Path="WidthInMMInCodeBehind" /> 
        <Binding Path="FallbackWidthInPixelsInCodeBehind" /> 
       </MultiBinding.Bindings> 
      </MultiBinding> 
     </Border.Width> 

Voilà!

相關問題