簡體   English   中英

在 ControlTemplate 上覆蓋 IsMouseOver 會使按鈕消失

[英]Overriding IsMouseOver on ControlTemplate makes Button disappear

我是 WPF 的新手,我正在嘗試為我的應用程序中的按鈕定義按鈕樣式。 我添加了以下ResourceDictionary並將其添加到App.xaml的應用程序資源中:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:ReciepeFinder">

<Style x:Key="NavButton" TargetType="Button">

    <Setter Property="Width"
            Value="120" />
    <Setter Property="Height"
            Value="120" />
    <Setter Property="BorderThickness"
            Value="0" />

    <Setter Property="Background">
        <Setter.Value>
            <ImageBrush ImageSource="/ReciepeFinder;component/resources/images/home.png" />
        </Setter.Value>
    </Setter>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver"
                             Value="True">
                        <Setter Property="Background">
                            <Setter.Value>
                                <ImageBrush ImageSource="/ReciepeFinder;component/resources/images/home_selected.png" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

</Style>

基本上,在沒有懸停時,我希望按鈕顯示resources/images/home.png並在懸停時顯示resources/images/home_selected.png 當我嘗試按照上面的代碼定義ControlTemplate並運行應用程序時,該按鈕沒有出現。 但是,如果我完全刪除ControlTemplate標記,則該按鈕具有正確的Background ,但顯然沒有懸停效果。 我究竟做錯了什么?

額外問題:如果我想使用綁定以便我可以在其他按鈕的屬性中設置無懸停圖像和懸停圖像的路徑並使其行為相同,我怎么能做到這一點?

因為在設置 ControlTemplate 時,您基本上必須重新定義控件的顯示方式。 並且您只定義了沒有任何內容表示的觸發器。 ContentPresenter 控件將幫助您解決這個問題。 只需在 ControlTemplate.Triggers 和 ControlTemplate 之后添加一些邊框和內容展示器。 這應該可以解決問題:

</ControlTemplate.Triggers>
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>

如果要重新設計控件的外觀及其視覺狀態,則必須編輯其ControlTemplate 但是,控件模板包含控件必需部分的定義,以及它在不同狀態下的外觀和它們之間的轉換。 要使ControlTemplate按預期工作,您必須實現所有這些部分和狀態。 您可以在 MSDN 上找到每個內置控件所需部件和狀態的信息, 例如Button

您可以復制默認模板並對其進行調整,而不是從頭開始創建您的ControlTemplate ,這要容易得多。 您可以使用 Blend 或 Visual Studio 提取它。

您的控制模板不起作用,因為它本質上是空的。 沒有什么可以顯示背景或任何內容。 它不包含任何視覺效果或控件。 我已經為您創建了一個示例控件模板,它應該符合您的要求。

<Style x:Key="NavButton" TargetType="{x:Type Button}">
   <Setter Property="Background">
      <Setter.Value>
         <ImageBrush ImageSource="/ReciepeFinder;component/resources/images/home.png" />
      </Setter.Value>
   </Setter>
   <Setter Property="BorderThickness" Value="0"/>
   <Setter Property="HorizontalContentAlignment" Value="Center"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="Padding" Value="1"/>
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type Button}">
            <Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true"/>
            <ControlTemplate.Triggers>
               <Trigger Property="IsMouseOver" Value="true">
                  <Setter Property="Background" TargetName="border">
                     <Setter.Value>
                        <ImageBrush ImageSource="/ReciepeFinder;component/resources/images/home_selected.png" />
                     </Setter.Value>
                  </Setter>
               </Trigger>
               <Trigger Property="IsEnabled" Value="false">
                  <Setter TargetName="border" Property="Opacity" Value="0.5"/>
               </Trigger>
            </ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

Border顯示圖像背景。 通常,您會在Border內放置一個ContentPresenter ,因為它會顯示您分配給ButtonContent屬性的Content ,但由於您顯示的是圖像而不是內容,因此我將其省略。

請注意,此模板中有TemplateBinding 這些用於從應用模板的控件綁定指定的屬性。 換句話說,如果您直接在按鈕上設置Background或創建從設置它的NavButton派生的Style ,則將使用此值。 如果您只是對控件模板中的值進行硬編碼,則它不會更改。

對於您的額外問題:當您使用這些TemplateBinding ,直接或在派生Style設置Background將按上述方式工作,因此您可以重用它。 由於沒有HoverBackground屬性,您必須創建一個派生按鈕並為其添加依賴屬性,創建附加屬性或使用例如未使用的Foreground屬性,盡管這感覺不對,因為它很臟解決方法。 這是Foreground一個示例,只是因為它很容易為您測試,但它也適用於上述其他選項。

<Setter Property="Foreground">
   <Setter.Value>
      <ImageBrush ImageSource="/ReciepeFinder;component/resources/images/home_selected.png" />
   </Setter.Value>
</Setter>
<Trigger Property="IsMouseOver" Value="true">
   <Setter Property="Background" TargetName="border" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}"/>
</Trigger>

請注意,要訪問Setter模板化父項的屬性,您必須使用不同的綁定語法,其效果與TemplateBinding相同。

暫無
暫無

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

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