2013-08-07 46 views
1

我試圖創建一個包含圖像和文本的按鈕。但是,圖像可以在運行時由代碼改變。我的圖片PNG,每個人都在我的ResourceDictionary如:WPF帶圖像+文本按鈕並更改代碼隱藏圖像

<BitmapImage x:Key="iconLogIn" UriSource="/Images/Icons/lock.png" /> 

所以,我已經開始使用這種風格,沒有模板或的ContentTemplate。

<Style x:Key="MyTestButton" TargetType="{x:Type Button}"> 
    <Setter Property="Height" Value="80" /> 
    <Setter Property="Width" Value="100" /> 
</Style> 

我的XAML是:

<Button x:Name="cmdOption1" Style="{StaticResource MyTestButton}" Margin="8" Click="cmdOption1_Click"> 
    <Image Source="{DynamicResource iconLogIn}" /> 
</Button> 

然後,我後面的代碼來改變形象是:

cmdOption1.Content = new Image() { Source = ((BitmapImage)FindResource("iconLogOut")) }; 

到目前爲止,這個工程。

但是,只保留圖像,我想放置在圖像下的文本。

因此,我已閱讀this後,HighCore的答案選項#2可能會滿足我的要求。但是,現在提供了一個新的問題:

首先,這是新的風格,用一個簡單的模板

<Style x:Key="MyTestButton" TargetType="{x:Type Button}"> 
    <Setter Property="Background" Value="#EEEEEE" /> 
    <Setter Property="Foreground" Value="DarkSlateGray" /> 
    <Setter Property="Height" Value="80" /> 
    <Setter Property="Width" Value="100" /> 
    <Setter Property="HorizontalContentAlignment" Value="Center"/> 
    <Setter Property="VerticalContentAlignment" Value="Center"/> 
    <Setter Property="Padding" Value="2"/> 
    <Setter Property="FontSize" Value="12" /> 
    <Setter Property="FontWeight" Value="SemiBold" /> 
    <Setter Property="BorderThickness" Value="1" /> 
    <Setter Property="BorderBrush" Value="DarkGray" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type Button}"> 
       <Border> 
        <StackPanel> 
         <Image Source="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}" Height="50" Width="50"/> 
         <ContentPresenter Grid.Row="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" /> 
        </StackPanel> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsPressed" Value="True"> 
         <Setter Property="Foreground" Value="DarkOrange" /> 
         <Setter Property="OpacityMask" Value="#AA888888"/> 
        </Trigger> 
        <Trigger Property="IsEnabled" Value="false"> 
         <Setter Property="Foreground" Value="Gray" /> 
         <Setter Property="BorderBrush" Value="DarkGray" /> 
         <Setter Property="Background" Value="White" /> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
</Style> 

我的新XAML是:

<Button x:Name="cmdOption1" Tag="{StaticResource iconLogIn}" Content="LOG IN" Style="{StaticResource MyTestButton}" Margin="8" Click="cmdOption1_Click" /> 

*也與標籤=「{ DynamicResource iconLogIn}」

而且我後面的代碼來改變圖片和文字:

cmdOption1.Tag = new Image() { Source = ((BitmapImage)FindResource("iconLogOut")) }; 
cmdOption1.Content = "LOG OUT"; 

這樣,內容文本從「登錄」變爲「登出」。但是圖像不再顯示,圖像中沒有任何內容,也沒有錯誤或異常。

我想知道最新的解決方案,發生了什麼?爲什麼圖像只是沒有改變,但消失了?

在此先感謝。

回答

0

您創建一個新的圖像控件並將其分配給按鈕的Tag屬性。因此,ControlTemplate中的Image控件將其Source屬性設置爲另一個Image控件。這是行不通的。只需將資源中的BitmapImage分配給Tag即可。

而不是

cmdOption1.Tag = new Image() { Source = ((BitmapImage)FindResource("iconLogOut")) }; 

,你應該簡單地寫:

cmdOption1.Tag = (BitmapImage)FindResource("iconLogOut"); 
0

你的XAML工作正常。在必要的代碼,唯一要設置Image這樣:

private void cmdOption1_Click(object sender, RoutedEventArgs e) 
{ 
    BitmapImage MyBitmapImage = ((BitmapImage)FindResource("iconLogOut")); 
    cmdOption1.Tag = MyBitmapImage; 

    cmdOption1.Content = "LOG OUT"; 
} 

作爲替代(只是比較方法),你可以使用這一招不通過功能FindChild<>使用Tag。您的模板的一部分:

<ControlTemplate TargetType="{x:Type Button}"> 
    <Border> 
     <StackPanel> 
      <Image x:Name="MyContentImage" Source="{StaticResource iconLogIn}" Height="50" Width="50" /> 
      <ContentPresenter Grid.Row="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" /> 
     </StackPanel> 
    </Border> 

    ... 

後面的代碼:

上市 FindChild<>
private void cmdOption1_Click(object sender, RoutedEventArgs e) 
{ 
    // Find the Image in template 
    Image MyContentImage = FindChild<Image>(cmdOption1, "MyContentImage"); 
    MyContentImage.Source = ((BitmapImage)FindResource("iconLogOut")); 

    cmdOption1.Content = "LOG OUT"; 
} 

public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject 
    { 
     if (parent == null) 
     { 
      return null; 
     } 

     T foundChild = null; 

     int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 

     for (int i = 0; i < childrenCount; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parent, i); 
      T childType = child as T; 

      if (childType == null) 
      { 
       foundChild = FindChild<T>(child, childName); 

       if (foundChild != null) break; 
      } 
      else 
       if (!string.IsNullOrEmpty(childName)) 
       { 
        var frameworkElement = child as FrameworkElement; 

        if (frameworkElement != null && frameworkElement.Name == childName) 
        { 
         foundChild = (T)child; 
         break; 
        } 
        else 
        { 
         foundChild = FindChild<T>(child, childName); 

         if (foundChild != null) 
         { 
          break; 
         } 
        } 
       } 
       else 
       { 
        foundChild = (T)child; 
        break; 
       } 
     } 

     return foundChild; 
    } 
5

我認爲你應該考慮一個更簡潔的方法,通過使用MVVM,與數據綁定和實施INotifyPropertyChanged。

起初:使用視圖模型中定義其定義ImageUri屬性和文本:

private Uri _myImageUriProperty; 
    public Uri MyImageUriProperty 
    { 
     get { return _myImageUriProperty; } 
     set { _myImageUriProperty = value; RaisePropertyChanged(() => MyImageUriProperty); } 
    } 

    private string _myTextBlockProperty; 
    public string MyTextBlockProperty 
    { 
     get { return _myTextBlockProperty; } 
     set { _myTextBlockProperty = value; RaisePropertyChanged(() => MyTextBlockProperty); } 
    } 

此外:裏面你的按鈕,你可以使用一個佔位符把你的按鈕中的多個UI元素。

<Button x:Name="MyButton" 
      Click="MyButton_OnClick"> 
     <StackPanel> 
      <Image x:Name="MyImage" 
        Source="{Binding MyImageUriProperty}" /> 
      <TextBlock x:Name="MyTextBlock" 
         Text="{Binding MyTextBlockProperty}" /> 
     </StackPanel> 
    </Button> 

最後::使用click事件的代碼隱藏在你的視圖模型值重置(你在你的代碼隱藏的構造已設置爲在DataContext的,並將它們從您的視圖模型綁定到你的屬性PropertyChanged事件將觸發用戶界面中的更新

private void MyButton_OnClick(object sender, RoutedEventArgs e) 
    { 
     ViewModel.MyImageUriProperty = new Uri("mynewuri.png", UriKind.Relative) 
     ViewModel.MyTextBlockProperty = "LogOut"; 
    } 
+0

我喜歡你的答案,由於時間限制,我無法更改爲MVVM。 – BlackCath