2015-11-06 21 views
12

Tôi gặp sự cố khi tạo điều khiển xaml. Tôi đang viết dự án mới trong VS 2015 trong ứng dụng toàn cầu. Tôi muốn tạo lưới. Trong lưới này tôi muốn có một nút. Trong mô hình tôi specifi cột (Level) và Row. đây là mã của tôi:UWP Binding in Style Setter không hoạt động

<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=TechnologyList}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
        <RowDefinition Height="10*"/> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
        <ColumnDefinition Width="14*"/> 
       </Grid.ColumnDefinitions> 
      </Grid> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
     <Style TargetType="Control"> 
      <Setter Property="Grid.Column" Value="{Binding Level}" /> 
      <Setter Property="Grid.Row" Value="{Binding Row}" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Button Content="{Binding Name}"/> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

tôi nhận được một lỗi trong dòng <Setter Property="Grid.Column" Value="{Binding Level}" /> Các lỗi: ngoại lệ từ HRESULT: 0x8000FFFF (E_UNEXPECTED) là trong edytor không chạy mã. Có gì sai? Trong "cũ" WPF mọi thứ đều OK nhưng trong Universal App cho Windows 10 tôi có một lỗi. Có ai giúp tôi không?

+1

Tôi có thể làm điều gì đó như thế này n UWP? – Babel

Trả lời

21

Như đã lưu ý trong phần Ghi chú di chuyển trên trang Setter.Value property trên MSDN, UWP/Windows Runtime không hỗ trợ các liên kết trong Trình định kiểu kiểu.

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from WPF or Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding-obtained values.

Cách giải quyết có thể là lớp trợ giúp có thuộc tính đính kèm cho đường dẫn nguồn của các ràng buộc. Nó tạo ra các ràng buộc trong mã phía sau trong một PropertyChangedCallback tài sản helper:

public class BindingHelper 
{ 
    public static readonly DependencyProperty GridColumnBindingPathProperty = 
     DependencyProperty.RegisterAttached(
      "GridColumnBindingPath", typeof(string), typeof(BindingHelper), 
      new PropertyMetadata(null, GridBindingPathPropertyChanged)); 

    public static readonly DependencyProperty GridRowBindingPathProperty = 
     DependencyProperty.RegisterAttached(
      "GridRowBindingPath", typeof(string), typeof(BindingHelper), 
      new PropertyMetadata(null, GridBindingPathPropertyChanged)); 

    public static string GetGridColumnBindingPath(DependencyObject obj) 
    { 
     return (string)obj.GetValue(GridColumnBindingPathProperty); 
    } 

    public static void SetGridColumnBindingPath(DependencyObject obj, string value) 
    { 
     obj.SetValue(GridColumnBindingPathProperty, value); 
    } 

    public static string GetGridRowBindingPath(DependencyObject obj) 
    { 
     return (string)obj.GetValue(GridRowBindingPathProperty); 
    } 

    public static void SetGridRowBindingPath(DependencyObject obj, string value) 
    { 
     obj.SetValue(GridRowBindingPathProperty, value); 
    } 

    private static void GridBindingPathPropertyChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var propertyPath = e.NewValue as string; 

     if (propertyPath != null) 
     { 
      var gridProperty = 
       e.Property == GridColumnBindingPathProperty 
       ? Grid.ColumnProperty 
       : Grid.RowProperty; 

      BindingOperations.SetBinding(
       obj, 
       gridProperty, 
       new Binding { Path = new PropertyPath(propertyPath) }); 
     } 
    } 
} 

Bạn sẽ sử dụng chúng trong XAML như thế này:

<ItemsControl.ItemContainerStyle> 
    <Style TargetType="ContentPresenter"> 
     <Setter Property="local:BindingHelper.GridColumnBindingPath" Value="Level"/> 
     <Setter Property="local:BindingHelper.GridRowBindingPath" Value="Row"/> 
    </Style> 
</ItemsControl.ItemContainerStyle> 

Đối với một workaround đơn giản cho việc định vị tuyệt đối (tức là ràng buộc các thuộc tính Canvas.Leftcanvas.Top), xem this answer.

+0

Hm không làm việc cho tôi. Targettype trong ItemContainerStyle luôn là ContentPresenter? Nếu tôi đặt nó vào ViewModel của mình, tôi sẽ nhận được một ngoại lệ thất bại thảm khốc. –

+0

@ MatthiasMüller, tôi nghĩ điều đó đúng. Tôi đã có một vấn đề tương tự. ContentPresenter là cha mẹ của toàn bộ mẫu, vì vậy tôi tin rằng đó là loại mục tiêu chính xác. – rbwhitaker

+0

Loại vùng chứa của một ItemsControl là ContentPresenter, do đó TargetType của một ItemContainerStyle phải là ContentPresenter. – Clemens

0

Muốn thêm trải nghiệm của tôi về ý tưởng này BindingHelper từ @clemens. Đó là một giải pháp gọn gàng nhưng tôi thấy rằng khi nhắm mục tiêu ListViewItem ràng buộc sẽ không truy cập vào mô hình chế độ xem cơ bản. Sau khi gỡ lỗi, tôi thấy rằng tôi cần đảm bảo rằng ràng buộc liên quan đến chính số ListViewItem và thuộc tính được liên kết .Content để cho phép liên kết chính xác với mô hình chế độ xem của mặt hàng.

trường hợp sử dụng cụ thể của tôi là thiết lập các IsTabStop tài sản của ListViewItem dựa trên một giá trị quan điểm mô hình:

private static void BindingPathPropertyChanged(DependencyObject obj, 
    DependencyPropertyChangedEventArgs e) 
{ 
    if (e.NewValue is string propertyPath) 
    { 
     var binding = new Binding 
     { 
      Path = new PropertyPath($"Content.{propertyPath}"), 
      Mode = BindingMode.OneWay, 
      RelativeSource = new RelativeSource 
      { 
       Mode = RelativeSourceMode.Self 
      } 
     }; 
     BindingOperations.SetBinding(obj, Control.IsTabStopProperty, binding); 
    } 
} 

Hope this helps nếu bất cứ ai khác có vấn đề.

Các vấn đề liên quan