2009-12-20 34 views
7

Tôi đang tạo điều khiển tùy chỉnh WPF, Button với ImageText. Tôi đã thêm hai thuộc tính phụ thuộc vào điều khiển, ImagePathText và mẫu điều khiển (trong Chủ đề \ Generic.xaml) là một bảng ngăn xếp đơn giản sắp xếp hình ảnh và văn bản theo chiều ngang.Điều khiển tùy chỉnh WPF: TemplateBinding to Image

Tài sản Text hoạt động tốt. Nhưng vì lý do nào đó, hình ảnh mẫu trong dự án thử nghiệm của tôi không xuất hiện khi tôi sử dụng TemplateBinding đến thuộc tính phụ thuộc ImagePath để có được đường dẫn của nó. Tôi đã thử nghiệm hình ảnh bằng cách tạm thời thay thế TemplateBinding trong điều khiển tùy chỉnh bằng đường dẫn đến hình ảnh, trong trường hợp này nó xuất hiện.

Tôi hy vọng rằng ai đó có nhiều kinh nghiệm trong lĩnh vực này có thể xem và cho tôi biết lý do kiểm soát không hoạt động như mong đợi. Cảm ơn bạn đã giúp đỡ.

Giải pháp VS 2008 của tôi chứa một dự án, CustomControlDemo. Dự án có một điều khiển tùy chỉnh, TaskButton.cs và một cửa sổ chính, Window1.xaml, mà tôi sử dụng để kiểm tra điều khiển. Hình ảnh thử nghiệm của tôi, calendar.png, nằm trong thư mục Tài nguyên ở cấp cơ sở của dự án và Generic.xaml nằm trong thư mục Chủ đề, cũng ở cấp cơ sở của dự án.

Đây là đoạn mã để điều khiển tùy chỉnh của tôi (từ TaskButton.cs):

using System.Windows; 
using System.Windows.Controls; 

namespace CustomControlDemo 
{ 
    public class TaskButton : RadioButton 
    { 
     #region Fields 

     // Dependency property backing variables 
     public static readonly DependencyProperty ImagePathProperty; 
     public static readonly DependencyProperty TextProperty; 

     #endregion 

     #region Constructors 

     /// <summary> 
     /// Default constructor. 
     /// </summary> 
     static TaskButton() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(TaskButton), new FrameworkPropertyMetadata(typeof(TaskButton))); 

      // Initialize ImagePath dependency properties 
      ImagePathProperty = DependencyProperty.Register("ImagePath", typeof(string), typeof(TaskButton), new UIPropertyMetadata(null)); 
      TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TaskButton), new UIPropertyMetadata(null)); 
     } 

     #endregion 

     #region Dependency Property Wrappers 

     /// <summary> 
     /// The ImagePath dependency property. 
     /// </summary> 
     public string ImagePath 
     { 
      get { return (string)GetValue(ImagePathProperty); } 
      set { SetValue(ImagePathProperty, value); } 
     } 

     /// <summary> 
     /// The Text dependency property. 
     /// </summary> 
     public string Text 
     { 
      get { return (string)GetValue(TextProperty); } 
      set { SetValue(TextProperty, value); } 
     } 

     #endregion 
    } 
} 

Và đây là sự kiểm soát mẫu (từ Generic.xaml):

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


    <Style TargetType="{x:Type local:TaskButton}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type local:TaskButton}"> 
        <StackPanel Height="Auto" Orientation="Horizontal"> 
         <Image Source="{TemplateBinding ImagePath}" Width="24" Height="24" Stretch="Fill"/> 
         <TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Left" Foreground="{DynamicResource TaskButtonTextBrush}" FontWeight="Bold" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" /> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

Và cuối cùng, đây là đánh dấu Window1 mà tôi đang sử dụng để kiểm tra điều khiển:

<Window x:Class="CustomControlDemo.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:customControl="clr-namespace:CustomControlDemo" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <customControl:TaskButton ImagePath="Resources\calendar.png" Text="Calendar" /> 
    </Grid> 
</Window> 

Mọi ý tưởng tại sao đường dẫn hình ảnh không phải là wor nhà vua? Cảm ơn một lần nữa.

Trả lời

4

Hình ảnh không lấy chuỗi dưới dạng nguồn :) Bạn có thể thấy điều này trong phần intellisense. Bạn cần phải liên kết trên một ImageSource (Hoặc sử dụng một IValueConverter để chuyển đổi chuỗi thành một ImageSource)

Xem this câu hỏi về một số mẹo về cách thực hiện chuyển đổi này.

9

Tôi sẽ để lại câu trả lời của cwap là câu trả lời được chấp nhận, bởi vì nó là chính xác về mặt kỹ thuật. Tuy nhiên, nó chỉ ra rằng có một cách dễ dàng hơn để giải quyết vấn đề này.

MẫuCác đối tượng không phải là đối tượng ràng buộc hạng nhất. Chúng được thiết kế để có trọng lượng nhẹ, vì vậy chúng là một chiều và chúng thiếu một số tính năng của các đối tượng Binding khác. Đáng chú ý nhất, chúng không hỗ trợ các trình chuyển đổi kiểu đã biết được liên kết với một mục tiêu. Xem MacDonald, Pro WPF trong C# 2008, tr. 872. Đó là lý do tại sao cwap trả lời chính xác rằng tôi có lẽ sẽ cần tạo trình chuyển đổi kiểu và tham chiếu nó cụ thể trong mẫu điều khiển cho nút tuỳ chỉnh của tôi.

Nhưng tôi không phải sử dụng một TemplateBinding để liên kết mẫu điều khiển với thuộc tính ImagePath của điều khiển tùy chỉnh của tôi. Tôi có thể sử dụng một đối tượng Binding cũ đơn giản.Dưới đây là đánh dấu sửa đổi cho mẫu điều khiển tùy chỉnh của tôi:

<!-- Task Button Default Control Template--> 
<Style TargetType="{x:Type local:TaskButton}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:TaskButton}"> 
       <StackPanel Height="Auto" Orientation="Horizontal"> 
        <Image Source="{Binding Path=ImagePath, RelativeSource={RelativeSource TemplatedParent}}" Width="24" Height="24" Stretch="Fill" Margin="10,0,0,0" /> 
        <TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Left" Foreground="{TemplateBinding Foreground}" FontWeight="Bold" Margin="5,0,10,0" VerticalAlignment="Center" FontSize="12" /> 
       </StackPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Nếu bạn nhìn vào ImageControl trong mẫu, bạn có thể thấy sự thay đổi. Lưu ý thuộc tính RelativeSource trong cùng một đối tượng. Đặt thuộc tính này thành = {RelativeSource TemplatedParent} là những gì cho phép tôi nhập một đường dẫn tương đối trong cá thể Window1 của TaskButton và giải quyết nó một cách chính xác trong điều khiển tùy chỉnh.

Vì vậy, đề xuất của tôi cho những người khác nghiên cứu chuỗi này sẽ là bỏ qua công cụ chuyển đổi giá trị và chỉ cần chuyển từ Liên kết mẫu thành Ràng buộc cho thuộc tính Hình ảnh.

Cũng xin cảm ơn Marco Zhou, người đã cung cấp this answer cho một câu hỏi tương tự trong diễn đàn WPF của MSDN.

2

Thực ra cả hai câu trả lời đều không chính xác.

{TemplateBinding ImagePath} không gì khác ngoài lối tắt cho {Binding Path=ImagePath, RelativeSource={RelativeSource TemplatedParent}} và như vậy gần như hoàn toàn giống hệt nhau.

Ngoài ra, nếu bạn cung cấp chuỗi cho ImagePath, nó sẽ giải quyết chính xác đến ImageSource mặc dù bạn có hiệu suất ứng dụng. Vấn đề thực sự phải làm với đường dẫn hình ảnh tương đối và tuyệt đối trên số ImagePath="Resources\calendar.png" được cung cấp trong xaml cho thử nghiệm. Điều này gợi ý trình biên dịch nghĩ rằng đường dẫn được cung cấp là tuyệt đối vì việc sử dụng \ thay vì/trong việc xác định đường dẫn.

Lý do hình thức liên kết dài hoạt động và phím tắt không phải là nó cung cấp manh mối cho trình biên dịch rằng nguồn của hình ảnh được cung cấp (Resources \ calendar.png) là một đường dẫn tương đối chứ không phải đường dẫn tuyệt đối , do đó hình ảnh được tìm thấy và các công trình ràng buộc. Nếu bạn gỡ lỗi ràng buộc, bạn sẽ thấy phím tắt cố gắng giải quyết chuỗi được cung cấp vào nguồn hình ảnh nhưng không thể tìm thấy tệp "Resources \ calendar.png" Nếu bạn cung cấp URI đầy đủ cho hình ảnh tức là "C:\...\Resources\calendar.png" hoặc ký hiệu kết hợp tương ứng của "/application;component/Resources/calendar.png" sau đó hình ảnh sẽ được tìm thấy và ràng buộc được giải quyết.

Điểm này trở nên thực sự quan trọng khi bạn đang cố gắng tham chiếu hình ảnh từ một nguồn bên ngoài thay vì những nguồn được biên dịch thành tài nguyên trong quá trình biên dịch cuối cùng.

0

cách đơn giản (thử nghiệm) 1-làm ValueConverter bạn như thế này

public class objectToImageSourceConverter:IValueConverter 
    { 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 

      string packUri =value.ToString(); 
      ImageSource Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource; 
      return Source; 
     } 

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

2-ràng buộc Nguồn hình ảnh của bạn để properety chuỗi của cha mẹ (i dùng "tag" tài sản) như XAML này:

<Image HorizontalAlignment="Right" Height="Auto" Margin="0,11.75,5.5,10.75" VerticalAlignment="Stretch" Width="40.997" Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"/> 
Các vấn đề liên quan