2016-01-22 6 views
0

Я испытываю очень странное поведение с ItemTemplate ItemsControl. Некоторые из BindingExperssions возвращают null, хотя DataContext.WPF: BindingExpression возвращает null, хотя свойство source имеет значение

Вот XAML в вопросе:

<ItemsControl ItemsSource="{Binding Path=Index}" Grid.Row="1" Grid.Column="0" x:Name="RowsControl"> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <StackPanel/> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate DataType="{x:Type models:IndexCell}"> 
          <Border Style="{StaticResource CellBorderStyle}" 
            Background="{Binding BackgroundColor, Converter={StaticResource ColorToBrushConverter}}" 
            ToolTip="{Binding Path=ToolTip}"> 

           <TextBlock Text="{Binding Path=Content}" MouseDown="TextBlock_MouseDown" 
              HorizontalAlignment="{Binding Path=HorizontalTextAlignment}" 
              VerticalAlignment="Center"/> 
          </Border> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 

Так, например, я могу видеть, что визуально Контент свойство из DataContext извлекается. Значения I планирующие действительно показаны на screen.However, HorizontalTextAlignment выдает ошибку в окне Output в Visual Studio:

System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' BindingExpression:Path=HorizontalTextAlignment; DataItem='IndexCell' (HashCode=40508359); target element is 'TextBlock' (Name=''); target property is 'HorizontalAlignment' (type 'HorizontalAlignment') 

Свойства в объекте DataContext имеет правильный тип (System.Windows.HorizontalAlignment) и значение (я установил один по умолчанию, и это перечисление, так что «нет шанса» быть нулевым).

Я также провел еще один тест с IValueConverter. Когда Path указывается в Binding, конвертер получает нуль. Когда пути нет, он получает весь объект, и я его отлаживал, и он имеет значение для свойства. Кажется, что в WPF есть ошибка, но я действительно надеюсь, что я ошибаюсь.

У кого-нибудь есть идея, почему и как это происходит? Может, как я могу это исправить?

EDIT (по запросу): Вот интерфейс объекта DataContext

public interface ICell 
{ 
    string Content { get; set; } 
    Color TextColor { get; set; } 
    Color BackgroundColor { get; set; } 
    double FontSize { get; set; } 
    FontWeight FontWeight { get; set; } 
    TextWrapping TextWrapping { get; set; } 
    HorizontalAlignment HorizontalTextAlignment { get; set; } 
    VerticalAlignment VerticalTextAlignment { get; set; } 
    string ToolTip { get; set; } 
} 

И ItemsSource собственности из ViewModel:

private IReadOnlyList<ICell> _index; 
    public IReadOnlyList<ICell> Index 
    { 
     get { return _index; } 
     private set 
     { 
      if (_index == value) 
       return; 
      _index = value; 
      RaisePropertyChanged(); 
     } 
    } 

EDIT2: Вот код BasicCell

public abstract class BasicCell : BasicProxyElement, ICell 
{ 

    [StyleProperty] 
    public Color BackgroundColor 
    { 
     get 
     { 
      return this.GetProperty<Color>("BackgroundColor", Color.FromArgb(0, 0, 0, 0)); 
     } 
     set 
     { 
      if (value == BackgroundColor) 
      { 
       return; 
      } 

      if (this.TrySetProperty("BackgroundColor", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public string Content 
    { 
     get 
     { 
      return this.GetProperty<string>("Content", ""); 
     } 
     set 
     { 
      if (value == Content) 
      { 
       return; 
      } 

      if (this.TrySetProperty("Content", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public double FontSize 
    { 
     get 
     { 
      return this.GetProperty<double>("FontSize", 11d); 
     } 
     set 
     { 
      if (value == FontSize) 
      { 
       return; 
      } 

      if (this.TrySetProperty("FontSize", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public FontWeight FontWeight 
    { 
     get 
     { 
      return this.GetProperty<FontWeight>("FontWeight", FontWeights.Normal); 
     } 
     set 
     { 
      if (value == FontWeight) 
      { 
       return; 
      } 

      if (this.TrySetProperty("FontWeight", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public HorizontalAlignment HorizontalTextAlignment 
    { 
     get 
     { 
      return this.GetProperty<HorizontalAlignment>("HorizontalTextAlignment", HorizontalAlignment.Center); 
     } 
     set 
     { 
      if (value == HorizontalTextAlignment) 
      { 
       return; 
      } 

      if (this.TrySetProperty("HorizontalTextAlignment", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public Color TextColor 
    { 
     get 
     { 
      return this.GetProperty<Color>("TextColor", Color.FromArgb(255, 0, 0, 0)); 
     } 
     set 
     { 
      if (value == TextColor) 
      { 
       return; 
      } 

      if (this.TrySetProperty("TextColor", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public TextWrapping TextWrapping 
    { 
     get 
     { 
      return this.GetProperty<TextWrapping>("TextWrapping", TextWrapping.Wrap); 
     } 
     set 
     { 
      if (value == TextWrapping) 
      { 
       return; 
      } 

      if (this.TrySetProperty("TextWrapping", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public string ToolTip 
    { 
     get 
     { 
      return this.GetProperty<string>("ToolTip", null); 
     } 
     set 
     { 
      if (value == ToolTip) 
      { 
       return; 
      } 

      if (this.TrySetProperty("ToolTip", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 
    [StyleProperty] 
    public VerticalAlignment VerticalTextAlignment 
    { 
     get 
     { 
      return this.GetProperty<VerticalAlignment>("VerticalTextAlignment", VerticalAlignment.Center); 
     } 
     set 
     { 
      if (value == VerticalTextAlignment) 
      { 
       return; 
      } 

      if (this.TrySetProperty("VerticalTextAlignment", value)) 
      { 
       this.RaisePropertyChanged(); 
      } 
     } 
    } 

    public BasicCell(IGraphElement dataElement, IProxyGraph graph, string visualTarget) : base(dataElement, graph, visualTarget) 
    { 
    } 
} 

и Индекс:

public class IndexCell : BasicCell 
{ 
    private static readonly IProxyElementFactory _factory = new DelegateProxyElementFactory("IndexCell", 
     (graphElement, controller, visualTarget) => new IndexCell(graphElement, controller, visualTarget)); 

    public static IProxyElementFactory Factory 
    { 
     get { return _factory; } 
    } 

    private static readonly IStyleProvider _styleProvider = new ReflectionDefaultStyleProvider<IndexCell>(); 

    public static IStyleProvider StyleProvider 
    { 
     get { return _styleProvider; } 
    } 

    public IndexCell(IGraphElement dataElement, IProxyGraph graph, string visualTarget) : base(dataElement, graph, visualTarget) 
    { 
    } 
} 

спасибо!

+1

Не могли бы вы включить соответствующий код в конец –

+0

Кажется, что он работает нормально. Как вы строите коллекцию? –

+0

Возможно, ваша проблема возникает из-за того, что вы выполняете привязку к интерфейсу? Взгляните на этот вопрос, может быть полезно http://stackoverflow.com/questions/327984/wpf-databinding-to-interface-and-not-actual-object-casting-possible – lena

ответ

0

Единственный способ, которым я могу создать исключение было как этот

public interface ICell 
{ 
    string Content { get; set; } 
    Color TextColor { get; set; } 
    Color BackgroundColor { get; set; } 
    double FontSize { get; set; } 
    FontWeight FontWeight { get; set; } 
    TextWrapping TextWrapping { get; set; } 
    HorizontalAlignment? HorizontalTextAlignment { get; set; } 
    VerticalAlignment VerticalTextAlignment { get; set; } 
    string ToolTip { get; set; } 
} 

public class IndexCell : ICell 
{ 
    public string Content { get; set; } 
    public Color TextColor { get; set; } 
    public Color BackgroundColor { get; set; } 
    public double FontSize { get; set; } 
    public FontWeight FontWeight { get; set; } 
    public TextWrapping TextWrapping { get; set; } 
    public HorizontalAlignment? HorizontalTextAlignment { get; set; } 
    public VerticalAlignment VerticalTextAlignment { get; set; } 
    public string ToolTip { get; set; } 
} 

Поэтому убедитесь, что типа вы используете в IndexCell. Как-то тип может содержать нуль, достигает привязки.

Мое исключение:

System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' BindingExpression:Path=HorizontalTextAlignment; DataItem='IndexCell' (HashCode=55786324); target element is 'TextBlock' (Name=''); target property is 'HorizontalAlignment' (type 'HorizontalAlignment') 

Посмотрите свойство перечисления может возвращать значения, отличные от указанных в перечислении., например, попытайтесь применить любое целочисленное значение к любому перечислению.

public HorizontalAlignment HorizontalTextAlignment 
    { 
     get 
     { 
      return (HorizontalAlignment)100; 
     }    
    } 

Это будет нормально работать, и вы получите ошибку привязки во время выполнения (то же, что и ваша). Я не знаю вашу иерархию классов, поэтому не могу сказать точно. Но вы играете в generics здесь в методе GetProperty (...), чтобы он мог вернуть значение null. Единственный способ, которым вы можете точно знать, - отладить, как это происходит: < null>.

+0

Спасибо за попытку, но ваш код не отражает тот, который у меня есть. – user1509777

Смежные вопросы