簡體   English   中英

從 Generic.xml 中的樣式/模板訪問靜態對象?

[英]Accessing a static object from Style/template in Generic.xml?

我有一個名為LoadAnimAngle的 double,它簡單地保存旋轉加載圖標的角度,隨着時間的推移旋轉。 這個變量在我的MainViewModel類中定義。 我在所有具有旋轉加載圖標的地方都使用了相同的變量。

我需要在Generic.xml中使用樣式/模板定義的自定義控件中使用它。 這是我綁定到LoadAnimAngle的部分:

<v:ColoredImage Image="{StaticResource LoadingIcon}" Color="{StaticResource DarkBlueClick}" RenderTransformOrigin="0.5, 0.5" VerticalAlignment="Center" Width="32" Height="32" Margin="0,0,0,0" Visibility="{Binding IsBusy, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibility}}">
    <v:ColoredImage.RenderTransform>
       <RotateTransform Angle="{Binding MainViewModel.LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}}"/> //here is the error
    </v:ColoredImage.RenderTransform>
</v:ColoredImage>

自定義控件具有綁定到我的MainViewModel實例的屬性,如下所示:

public MainViewModel MainViewModel { get { return MainViewModel.instance; } }

MainViewModel的構造函數中,我簡單地設置了:

instance = this;

問題是Generic.xml在我的MainViewModel類之前加載,導致在加載圖形之前幀的實例為空,加載完所有內容后,一切正常。 我該如何解決這個問題?

System.Windows.Data 錯誤:2:找不到目標元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=MainViewModel.LoadAnimAngle; 數據項=空; 目標元素是 'RotateTransform' (HashCode=66939890); 目標屬性是“角度”(類型“雙”)

注意:我確實理解該錯誤是無害的,並且不會對最終用戶產生任何影響,但是每次調試時看到該錯誤都會讓我感到痛苦。

我需要在 Generic 之前以某種方式加載MainViewModel ,或者告訴 xaml 在 MainViewModel != null 之前不要嘗試從 LoadAnimAngle 獲取數據。

編輯

進行更改后,我得到了同樣的錯誤,因此我沒有直接綁定到MainViewModel的實例。 所以我認為我對問題案例的評價是錯誤的。

我添加了

    public double LoadAnimAngle
    {
        get
        {
            if (MainViewModel.instance != null)
            {
                return MainViewModel.instance.LoadAnimAngle;
            }
            return 0;
        }
    }

到視圖模型(而不是return MainViewModel.instance

然后我將綁定更改為:

Angle="{Binding Path=LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}"

我犯了同樣的錯誤:

System.Windows.Data 錯誤:2:找不到目標元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=LoadAnimAngle; 數據項=空; 目標元素是 'RotateTransform' (HashCode=21529561); 目標屬性是“角度”(類型“雙”)

如果問題不是MainViewModel.instance為 NULL,那么導致問題的原因是什么? 我在解碼錯誤消息中的語言時遇到問題。 究竟出了什么問題,為什么?

編輯 2

相關上下文 (?)

    <Style TargetType = "{x:Type v:ComPortButton}" >
    <Setter Property = "Background" Value = "{StaticResource Milky}"/>
    <Setter Property = "ColorPalette" Value = "{StaticResource MilkyPalette}"/>
    <Setter Property = "Foreground" Value = "{StaticResource Black}"/>
    <Setter Property = "BorderColor" Value = "{StaticResource Milky}"/>
    <Setter Property="IsBasicTextButton" Value="False"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type v:ComPortButton}">
                <Grid>
                    <Grid Visibility="{Binding Path=IsBasicTextButton, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBooleanToVisibility}}">
                        <Border BorderBrush="{TemplateBinding BorderColor}" Background="{TemplateBinding Background}" Width="128" Height="140" BorderThickness="1"/>

                        //REMOVED IREELEVANT CODE

                        <v:ColoredImage Image="{StaticResource LoadingIcon}" Color="{StaticResource DarkBlueClick}" RenderTransformOrigin="0.5, 0.5" VerticalAlignment="Center" Width="32" Height="32" Margin="0,0,0,0" Visibility="{Binding IsBusy, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibility}}">
<v:ColoredImage.RenderTransform>
   <RotateTransform Angle="{Binding MainViewModel.LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}}"/> //here is the error
</v:ColoredImage.RenderTransform>
</v:ColoredImage>

                    </Grid>
                    
                    //REMOVED IRRELEVANT CONTROL
                    </Grid>

                    //REMOVED IRRELEVANT CONTEXT MENU
                    
                </Grid>
                //REMOVED IRRELEVANT TRIGGERS
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

編輯 3

錯誤的來源似乎與我最初想象的完全不同。 該錯誤似乎與RenderTransform有關,因為我可以從其他地方訪問該屬性而不會出現錯誤。

像這樣:

// NO ERROR FOR TEXT BLOCK
<TextBlock Text="{Binding MainViewModel.LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}"/>
                        
<v:ColoredImage Image="{StaticResource LoadingIcon}" Color="{StaticResource DarkBlueClick}" RenderTransformOrigin="0.5, 0.5" VerticalAlignment="Center" Width="32" Height="32" Margin="0,0,0,0" Visibility="{Binding IsBusy, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibility}}">
    <v:ColoredImage.RenderTransform>
        // ERROR FOR ROTATETRANSFORM
        <RotateTransform Angle="{Binding MainViewModel.LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}"/>
    </v:ColoredImage.RenderTransform>
</v:ColoredImage>

但是當我不引用MainViewModel時,我也會收到錯誤消息。 我創建了一個這樣的新屬性:

    public double LoadAnimAngle
    {
        get
        {
            return 0;
        }
    }

然后我像這樣在模板中使用它:

                            <v:ColoredImage Image="{StaticResource LoadingIcon}" Color="{StaticResource DarkBlueClick}" RenderTransformOrigin="0.5, 0.5" VerticalAlignment="Center" Width="32" Height="32" Margin="0,0,0,0" Visibility="{Binding IsBusy, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibility}}">
                            <v:ColoredImage.RenderTransform>
                                <RotateTransform Angle="{Binding LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}"/>
                            </v:ColoredImage.RenderTransform>
                        </v:ColoredImage>

但我得到了完全相同的錯誤!

因此,財產有效,一切正常。 只是RenderTransform在實例化時第一幀就像在VisualTree之外? 或者類似的東西,我猜? RenderTransform 中發生了一些不同的事情,使它不喜歡我的綁定。

而且我可能不清楚結構。

ComPortButton是一個自定義控件(Generic.xml 中帶有模板/樣式的.cs 文件)。 ComPortButton使用ComPortVM作為它的DataContext 我想全局訪問旋轉值,不同的控件,不同的窗口,不同的一切,全局。 我有一個MainViewModel我目前在其中存儲值,因為它提供全局訪問,因為它

編輯 4

解決了它並在下面發布了解決方案

您的控件必須獨立於具體的視圖模型類型。 相反,將控件的內部綁定到此控件上的依賴項屬性。 然后讓外部視圖模型綁定到這個屬性(或在本地設置它們)。
通過這種方式,您可以消除控件和DataContext之間的緊密耦合,從而大大簡化了控件的實現。 它還允許控件與任何DataContext (視圖模型)一起重用。

ComPortButton.cs

class ComPortButton : Control
{
  public double Angle
  {
    get => (double)GetValue(AngleProperty);
    set => SetValue(AnglePropertyKey, value);
  }

  protected static readonly DependencyProperty AnglePropertyKey = DependencyProperty.RegisterReadOnly(
  "Angle",
  typeof(double),
  typeof(ComPortButton),
  new PropertyMetadata(default));

  public static readonly DependencyProperty AngleProperty = AnglePropertyKey..DependencyProperty;

  public double ProgressPercentage
  {
    get => (double)GetValue(ProgressPercentageProperty);
    set => SetValue(ProgressPercentageProperty, value);
  }

  public static readonly DependencyProperty ProgressPercentageProperty = DependencyProperty.Register(
  "ProgressPercentage",
  typeof(double),
  typeof(ComPortButton),
  new PropertyMetadata(default(double), OnProgressPercentageChanged));

  private static void OnProgressPercentageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    double percentage = (double)e.NewValue / 100;

    // Enforce an angle between 0°-360°
    this.Angle = Math.Max(0, Math.Min(360, 360 * percentage));
  }
}

通用的.xaml

<Style TargetType="ComPortButton">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type v:ComPortButton}">
        <v:ColoredImage>
          <v:ColoredImage.RenderTransform>
            <RotateTransform Angle="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Angle}" />
          </v:ColoredImage.RenderTransform>
        </v:ColoredImage>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

使用示例

<Window>
  <Window.DataContext>
    <MainViewModel />
  </Window.DataContext>

  <ComPortButton ProgressPercentage="{Binding ProgressPercentageValue}" />
</Window>

在我發現問題是 RenderTransform 而不是其他問題之后,很容易在網上找到解決方案,似乎很多人都遇到了同樣的問題。

這是幫助我解決它的線程

問題與 VisualTree 有關,模板中的 RenderTransform 在加載整個控件之前沒有連接到 VisualTree。 或類似的東西。

當像這樣綁定到 RotateTransform 時:

    <v:ColoredImage.RenderTransform>
        <RotateTransform Angle="{Binding LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}}"/>
    </v:ColoredImage.RenderTransform>

出現問題。 但是由於某些我不明白的原因,您可以通過綁定到 RenderTransform 來消除錯誤。 但為此,您需要一個轉換器。

[ValueConversion(typeof(double), typeof(RotateTransform))]
public class AngleToTransform : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        return new RotateTransform((double)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

然后像這樣使用轉換器:

<v:ColoredImage RenderTransform="{Binding MainViewModel.LoadAnimAngle, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource AngleToTransform}}"/>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM