I'm trying to bind my UserControl to a dependency property defined in my UserControl itself, but I keep getting a binding error:
BindingExpression path error: 'DefinitionTypeResourceKeyProperty' property not found on 'object' ''DefinitionsList' (Name='')'. BindingExpression:Path=DefinitionTypeResourceKeyProperty; DataItem='DefinitionsList' (Name=''); target element is 'ItemsControl' (Name=''); target property is 'ItemTemplate' (type 'DataTemplate')
This is my xaml:
<UserControl x:Class="Editor.Common.DefinitionsList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Editor.Common"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<local:StringToResourceConverter x:Key="StringToResource" />
</UserControl.Resources>
<Expander>
<Expander.ContextMenu>
<ContextMenu>
<MenuItem Header="Add"
Command="{Binding AddItem}" />
<MenuItem Header="Remove"
Command="{Binding RemoveItem}" CommandParameter="{Binding SelectedItem}" />
</ContextMenu>
</Expander.ContextMenu>
<Grid>
<ItemsControl ItemsSource="{Binding Items}" ItemTemplate="{Binding DefinitionTypeResourceKeyProperty, Converter={StaticResource StringToResource}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
</ItemsControl>
</Grid>
</Expander>
</UserControl>
and this is its .cs file:
using System.Windows;
using System.Windows.Controls;
namespace Editor.Common
{
public partial class DefinitionsList : UserControl
{
public string DefinitionTypeResourceKey
{
get { return (string)GetValue(DefinitionTypeResourceKeyProperty); }
set { SetValue(DefinitionTypeResourceKeyProperty, value); }
}
public static readonly DependencyProperty DefinitionTypeResourceKeyProperty =
DependencyProperty.Register("DefinitionTypeResourceKey", typeof(string), typeof(DefinitionsList));
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(DefinitionsList));
public DefinitionsList()
{
InitializeComponent();
}
}
}
I use this control as generic list control so I can put different types of controls in this list.
This is how I try to use it a for a specific kind of contorl:
<UserControl x:Class="Editor.Item.ItemEditorControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Editor.Item"
xmlns:component="clr-namespace:Editor.Component"
xmlns:common="clr-namespace:Editor.Common"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="compListTemplate">
<component:ComponentListEditorControl />
</DataTemplate>
</UserControl.Resources>
<common:DefinitionsList Header="{Binding Name}" DefinitionTypeResourceKey="compListTemplate" />
</UserControl>
and its .cs file:
using System.Windows.Controls;
namespace Editor.Item
{
public partial class ItemEditorControl : UserControl
{
public ItemEditorControl()
{
InitializeComponent();
DataContext = new ItemDefinitionViewModel();
}
}
}
Why am I getting this error?
I'm adding the ItemDefinitionViewModel code:
using Editor.Common;
namespace Editor.Item
{
public class ItemDefinitionViewModel : BaseViewModel<ItemEditorItem>
{
public ItemDefinitionViewModel()
{
}
}
}
And its base class:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
namespace Editor.Common
{
public class BaseViewModel<T> : INotifyPropertyChanged
where T : new()
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand AddItem { get; private set; }
public ICommand RemoveItem { get; private set; }
public ObservableCollection<T> Items { get; private set; }
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public BaseViewModel()
{
Items = new ObservableCollection<T>();
AddItem = new RelayCommand(addItem);
RemoveItem = new RelayCommand(removeItem);
}
private void removeItem(object obj)
{
T removedItem = (T)obj;
Items.Remove(removedItem);
}
private void addItem(object obj)
{
T newItem = new T();
Items.Add(newItem);
}
}
}
You bind to DefinitionTypeResourceKeyProperty instead of DefinitionTypeResourceKey. You're trying to bind to the DP definition instead of the DP.
Another thing that "bothers" me is that you're looking for a UserControl in your RelativeSource RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
.
Instead, you should look for a DefinitionsList. If you change that the editor will tell you you made a mistake on the DP name, saving you time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.