2012-03-03 10 views
6

Hãy xem xét các tập tin XAML sau:Tại sao x: chìa khóa yêu cầu trên ControlTemplate trong ResourceDictionary

<Window x:Class="ExpressionVisualizer.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type sle:BinaryExpression}"/> 
     <ControlTemplate TargetType="{x:Type ContentControl}"/> 
    </Window.Resources> 
</Window> 

này được đưa ra lỗi biên dịch sau:

All objects added to an IDictionary must have a Key attribute or some other type of key associated with them. Line 10 Position 10.

Nếu tôi thêm một thuộc tính x:key đến ControlTemplate, nó biên dịch. Tuy nhiên, tôi không phải làm vậy. ControlTemplate được trang trí với thuộc tính DictionaryKeyProperty, chỉ định TargetType là thuộc tính khóa. Vì vậy, miễn là tôi chỉ định TargetType cho ControlTemplate của mình, tôi nên không phải phải chỉ định khóa rõ ràng (tương tự như cách tôi không phải chỉ định một khóa trên DataTemplate mà tôi đã xác định).

Tôi có câu hỏi thứ hai và liên quan đến tiếp tuyến. Nếu tôi định nghĩa một ControlTemplate theo cách này (hoặc chỉ định một khóa hay không) trong XAML, nó sẽ tự động áp dụng cho tất cả các điều khiển kiểu ContentControl không chỉ định một mẫu khác, hay tôi phải nhúng ControlTemplate bên trong một Style để điều đó xảy ra?

Trả lời

4

Từ MSDN ControlTemplate:

If you have a standalone ControlTemplate in the resources section with the TargetType property set to a type, the ControlTemplate does not get applied to that type automatically. Instead, you need to specify an x:Key and apply the template explicitly.

Also note that the TargetType property is required on a ControlTemplate if the template
definition contains a ContentPresenter.

Vì vậy, các ControlTemplate không tự động áp dụng và bạn phải luôn xác định x:Key. Vì vậy, DictionaryKeyProperty không áp dụng.

tôi đã làm một số nghiên cứu:

Mặc dù DictionaryKeyPropertyAttribute bang trang MSDN:

WPF Usage Notes

The following list references examples of WPF APIs where this attribute is applied:

ControlTemplate.TargetType 

DataTemplate.DataTemplateKey 

Style.TargetType 

Nhưng trên trang Resources Overview họ chỉ đề cập đến Styles, DataTemplates, and Implicit Keys trong đó có phím ngầm. Điều này cũng ngụ ý rằng bạn cần luôn phải chỉ định x:Key cho ControlTemplate mặc dù số DictionaryKeyProperty.

Bằng cách có vẻ như đã xảy ra sự cố với số, hãy xem số connect issue này.

+0

Điều đó trả lời phần thứ hai của câu hỏi của tôi. Tôi biết tôi cần phải chỉ định một x: Key nếu tôi muốn tham khảo các mẫu ở nơi khác trong tài liệu, nhưng bỏ qua nó không nên gây ra một lỗi biên dịch. – luksan

+0

Tôi đã cập nhật câu trả lời của mình. Nó seams 'DictionaryKeyProperty' là không làm những gì nó phải là ... – nemesv

+0

Vấn đề với DictionaryKeyProperty xuất hiện không ảnh hưởng đến tất cả các loại, vì thuộc tính hoạt động như được chỉ định trên DataTemplate. Vấn đề Connect là từ năm 2009. Tôi đoán tôi sẽ chỉ viết điều này như là một điều khác trong WPF mà không hoạt động và chưa bao giờ được kiểm tra kỹ lưỡng. Mỗi khi tôi cố gắng phát triển một cái gì đó trong WPF, tôi chạy vào các loại vấn đề này. Điều này không bao giờ xảy ra với Windows Forms, mọi thứ chỉ hoạt động. Tôi thực sự nghĩ (có lẽ là mơ ước) rằng họ sẽ làm cho WPF dễ dự đoán hơn/có thể sử dụng được trong bản phát hành 4.0. – luksan

1

Tôi không biết câu trả lời cho câu hỏi đầu tiên của bạn, nhưng về thứ hai:

I have a second and tangentially related question. If I define a ControlTemplate in this way (either specifying a key or not) in the XAML, does it get automatically applied to all controls of type ContentControl that don't specify another template, or would I have to embed the ControlTemplate inside a Style for that to occur?

Không, nó sẽ không được tự động áp dụng. Kiểu được áp dụng tự động nếu khóa của chúng khớp với số DefaultStyleKey của điều khiển; các mẫu dữ liệu được chọn tự động bởi ContentControl nếu loại của Content khớp với số DataType của mẫu. Nhưng nó không phải là trường hợp cho các mẫu kiểm soát; dù sao, mẫu điều khiển thường được định nghĩa là một phần của kiểu kiểm soát, chúng hiếm khi được áp dụng trực tiếp cho điều khiển.

+0

+1 và cảm ơn, tôi không biết về DefaultStyleKey. – luksan

0
<Window x:Class="ExpressionVisualizer.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/> 
    <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/> 
</Window.Resources> 

chính được sử dụng để áp dụng khuôn mẫu về kiểm soát giống như nút, textbox, TextBlock vv Nếu bạn không sử dụng thì nó templating không hoạt động.

0

Nếu bạn muốn kiểm soát mẫu sẽ được áp dụng cho tất cả các loại quy định, bạn có thể xác định một phong cách và thiết lập thuộc tính Template và phong cách với TargetType để kiểm soát theo quy định của bạn:

<Window x:Class="ExpressionVisualizer.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/> 
    <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/> 
    <Style TargetType="ContentControl"> 
     <Setter Property="Template" Value="{StaticResource CT}"></Setter> 
    </Style> 
</Window.Resources> 

Tôi đã thử nghiệm điều này với một nút targettype nhưng tôi nghĩ rằng nó sẽ làm việc theo cách đó.