2013-02-06 54 views
2

我有以下Style變量在XAML樣式

<Style x:Key="ButtonBase" TargetType="Button"> 
     <Setter Property="Background" Value="#FF007BFF"/> 
     <Setter Property="Foreground" Value="White"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="Button"> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsPressed" Value="> 
           <Setter Property="Background" Value="Yellow" /> 
           <Setter Property="Foreground" Value="Black" /> 
          </Trigger> 
          <Trigger Property="IsPressed" Value="False"> 
           <Setter Property="Background" Value="#FF007BFF" /> 
           <Setter Property="Foreground" Value="White" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
       </ControlTemplate> 
      <Setter.Value> 
     </Setter> 
</Style> 

和繼承Style

<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}"> 
     <Setter Property="Margin" Value="10"/> 
     <Setter Property="Height" Value="200"/> 
</Style> 

我希望做的是能夠在基地設置的任意變量風格:

<Setter Variable="HoverColor" Value="Pink"/> 

然後,我可以使用我的觸發器:

<Trigger Property="IsPressed" Value="> 
    <Setter Property="Background" Value="{TemplateBinding HoverColor}" /> 
    <Setter Property="Foreground" Value="Black" /> 
</Trigger> 

最後,然後我可以將其覆蓋在我的繼承方式:

<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}"> 
    <Setter Property="Margin" Value="10"/> 
    <Setter Property="Height" Value="200"/> 
    <Setter Variable="HoverColor" Value="Red"/> 
</Style> 

有沒有辦法來實現這一目標?我已經看過靜態資源,但這些不能被覆蓋。另外,我不能使用任何需要代碼隱藏的東西,因爲我沒有代碼!

+0

你是什麼意思_「我沒有一個」_ - 你的邏輯在哪裏? – Blachshma

+0

這是MVVM應用程序中僅用於xaml的視圖。 – acron

+0

好的,對於這個MVVM視圖,你沒有ViewModel? – Blachshma

回答

2

這是一個很好的問題,我也通過這種事情進行了鬥爭。可能有某種僅用於XAML的方法可行,但我有一種感覺,如果存在,它會感覺很糟糕。我有幾個關於如何實現你想要的建議。

首先,快速觀察。你說你「沒有代碼隱藏」,並且你的觀點是「僅限XAML」。那麼,我從來沒有見過一個用戶控件視圖,至少沒有任何代碼隱藏文件,所以我假設你的意思是你只是不想把任何代碼放在那裏(除了強制性InitializeComponent())。話雖如此,我將概述的方法將不需要您的代碼隱藏文件中的代碼。

在一天結束時,聽起來像你真正想要的是定義一些自定義的「變量」。這些建議可以做到這一點,儘管可能不像您最初設想的那樣。

第一種方法,將解決你的問題是子類,你有興趣的造型,並添加任何自定義依賴屬性它的控制。例如,您可以繼承Button,如ButtonWithMyVariables。其中一個自定義依賴項屬性將被稱爲「HoverColor」,類型爲Color,或者更合適的,類型爲Brush的「HoverBrush」(如果您想直接將其應用於背景或前景屬性)。然後,您的基礎樣式可以將HoverColor設置爲任何想要的,並且您的繼承樣式可以覆蓋它,也可以直接在您的XAML中的元素上覆蓋它。我沒有提供這種方法的代碼示例(現在,除非請求),因爲這是一種更常用的方法,我猜你已經熟悉了。

第二種方法是定義一個自定義附加屬性。我還沒有看到這種方法用於嚴格處理樣式問題,這可能是因爲對於所附的「行爲」來完成其作業,作者已經使用樣式文件作出反應(綁定)並應用基於視覺的更改在附加屬性上,而不是附加屬性中的代碼改變了回調,在風格上做了一些事情(但我認爲它仍然可以這樣做)。但是,這種方法對許多人來說都是「輕量級」,因爲您不需要對任何現有控件進行子類化。

第二種方法的例子可以在MahApps.Metro庫中找到,特別是TextboxHelper class(其中包含附屬屬性)和Controls.TextBox.xaml style file(包含那些附屬屬性)。例如,我們看到了對TextBox控件模板,這條線,它利用了水印附加屬性:

<TextBlock x:Name="Message" 
      Text="{TemplateBinding Controls:TextboxHelper.Watermark}" Visibility="Collapsed" 
            Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.6" HorizontalAlignment="Left" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
            Margin="6,0,0,0"/> 

現在你可以想像,你可以設置水印值在基本風格的東西:

<Setter Property="Controls:TextboxHelper.Watermark" 
     Value="My helpful watermark for all!"/> 

,然後覆蓋它繼承的風格:

<Setter Property="Controls:TextboxHelper.Watermark" 
     Value="A more specific watermark!"/> 

不管採用哪種方法,我們可以定義任何「變量」我們希望,輕鬆地將它們放置在風格二傳手,OVE使用繼承的樣式,TemplateBind在控制模板內,或Trigger關閉。

+0

這兩種方法的唯一問題是需要引入外部名稱空間。我希望避免這種情況(我有點純粹主義者),但它可能是唯一的方法......謝謝你,無論哪種方式。 – acron

+0

很高興幫助。關於命名空間問題,如果您只是希望能夠使用這些方法而無需引用XAML命名空間前綴(即上面的「Controls」前綴),則可以使用一種技術來避免必須使用前綴。請參閱[** this **](http://stackoverflow.com/a/14611738/718325)。 –

+0

這種方法看起來不錯,但純粹是審美。實質上,在理想的世界中,我不希望我的View必須根本引用'ViewHelper'程序集。 – acron