I am currently getting the following error
System.Windows.Data Error: 40 : BindingExpression path error: 'EthernetView' property not found on 'object' ''LabelTextBox' (Name='Root')'. BindingExpression:Path=EthernetView.SessionName; DataItem='LabelTextBox' (Name='Root'); target element is 'LabelTextBox' (Name='Root'); target property is 'Text' (type 'String')
when I bind data to a custom control like
<controls:LabelTextBox Grid.Column="0" Padding="10,5,10,0" LabelText="Name" Text="{Binding EthernetView.SessionName}"
TextWidth="175" IsReadOnly="True" IsError="False" HorizontalAlignment="Right"/>
I am pretty sure I have my Dependency property on the object set up correctly
public partial class LabelTextBox : UserControl, INotifyPropertyChanged
{
public string Text
{
get { return LblTextBox.Text; }
set
{
SetValue(TextProperty, value);
LblTextBox.Text = value;
PropertyChanged(this, new PropertyChangedEventArgs("Text"));
}
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(LabelTextBox),
new PropertyMetadata(default(string), OnTextPropertyChanged));
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LabelTextBox source = d as LabelTextBox;
source.LblTextBox.Text = e.NewValue as string;
}
}
The xaml for the custom control looks like
<UserControl x:Class="Project.LabelTextBox"
x:Name="Root"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition x:Name="TextWidthColumn" Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="LeftLabel" Grid.Column="0" Foreground="Black" Padding="0,0,10,0" VerticalAlignment="Center" FontSize="12"
Text="{Binding LabelText, ElementName=Root, Mode=TwoWay}"/>
<Border x:Name="TextBoxBorder" Grid.Column="1" BorderThickness="2" Background="#FAFAFAFA">
<TextBox x:Name="LblTextBox" VerticalAlignment="Center" Margin="1" FontSize="12" Text="{Binding Text}"
TextChanged="LblTextBox_TextChanged" KeyDown="OnKeyDownHandler"/>
</Border>
<Image x:Name="ErrorImage" Grid.Column="2" Source="pack://application:,,,/Project;component/Images/RedX.ico" Height="12" Width="12"/>
<TextBlock x:Name="RightLabel" Grid.Column="3" Foreground="Black" Padding="10,0,0,0" VerticalAlignment="Center" FontSize="12"
Text="{Binding LabelText, ElementName=Root, Mode=TwoWay}"/>
</Grid>
</UserControl>
The code works properly at runtime, but I would like to clean up the output errors. Can anyone give me some insight on how to fix this error.
Dependency Properties looks like this (GetValue, SetValue!):
public readonly static DependencyProperty IsBusyProperty = DependencyProperty.Register(
"IsBusy", typeof(bool), typeof(BusyControl), new PropertyMetadata(false));
public bool IsBusy
{
get { return (bool)GetValue(IsBusyProperty); }
set { SetValue(IsBusyProperty, value); }
}
so yours is not right.
Related
i have a problem with the datacontext of nested user-controls. The Problem is that the Model in the ViewModel is binded on a DependencyProperty of the first user-control. In the first user-control is a second user-control. The second user-control has also a DependencyProperty. The first user-control binds on that DependencyProperty of the second user-control.
Mainview:
<UserControl x:Class="XXX.XXX.Hmi.Views.L1SetupViewerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
xmlns:uc="clr-namespace:XXX.XXX.Hmi.UserControls"
d:DesignHeight="450"
d:DesignWidth="800"
prism:ViewModelLocator.AutoWireViewModel="True"
Background="{DynamicResource BaseBrush}"
Foreground="{DynamicResource TextBrush}"
mc:Ignorable="d">
.
.
.
<GroupBox Grid.Row="1" Header="Entry Section">
<uc:L1SetupViewerEntrySectionView Margin="8" Setup="{Binding L1Setup}" />
</GroupBox>
.
.
.
</UserControl>
MainViewModel:
public class L1SetupViewerViewModel : ViewModelBase
{
private L1Setup _l1Setup;
private Pdi _pdi;
public L1SetupViewerViewModel()
{
Title = LanguageProvider.Instance.GetValue("L1SetupViewer_Window_Title");
LanguageProvider.Instance.UiCultureChanged += Instance_UiCultureChanged;
}
#region Properties
public L1Setup L1Setup
{
get { return _l1Setup; }
set { SetProperty(ref _l1Setup, value); }
}
public Pdi Pdi
{
get { return _pdi; }
set { SetProperty(ref _pdi, value); }
}
#endregion
#region Navigation
public override void OnNavigatedTo(NavigationContext navigationContext)
{
if (navigationContext.Parameters.ContainsKey("L1Setup"))
{
L1Setup = navigationContext.Parameters.GetValue<L1Setup>("L1Setup");
}
if (navigationContext.Parameters.ContainsKey("Pdi"))
{
Pdi = navigationContext.Parameters.GetValue<Pdi>("Pdi");
}
}
#endregion
private void Instance_UiCultureChanged(object sender, EventArgs e)
{
Title = LanguageProvider.Instance.GetValue("L1SetupViewer_Window_Title");
}
}
First UserControl:
<UserControl x:Class="XXX.XXX.Hmi.UserControls.L1SetupViewerEntrySectionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uc="clr-namespace:XXX.XXX.Hmi.UserControls"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
<ColumnDefinition Width="*" SharedSizeGroup="c" />
</Grid.ColumnDefinitions>
<uc:L1SetupViewerCellControl Title="Over Speed"
Grid.Row="0"
Grid.Column="0"
Margin="0,0,5,0"
Value="{Binding Setup.EnOveSpd}" />
.
.
.
</Grid>
</UserControl>
First UserControl CodeBehind:
public partial class L1SetupViewerEntrySectionView : UserControl
{
public L1Setup Setup
{
get { return (L1Setup)GetValue(SetupProperty); }
set { SetValue(SetupProperty, value); }
}
public static readonly DependencyProperty SetupProperty =
DependencyProperty.Register("Setup", typeof(L1Setup), typeof(L1SetupViewerEntrySectionView), new PropertyMetadata(null));
public L1SetupViewerEntrySectionView()
{
InitializeComponent();
this.DataContext = this;
}
}
Second UserControl:
<UserControl x:Class="XXX.XXX.Hmi.UserControls.L1SetupViewerCellControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Margin="0,0,3,0"
Text="{Binding Title}" />
<TextBox Grid.Column="1" Text="{Binding Value}" />
</Grid>
</UserControl>
Second UserControl CodeBehind:
public partial class L1SetupViewerCellControl : UserControl
{
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(L1SetupViewerCellControl), new PropertyMetadata(string.Empty));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(L1SetupViewerCellControl), new PropertyMetadata(string.Empty));
public L1SetupViewerCellControl()
{
InitializeComponent();
this.DataContext = this;
}
}
If i run the application i get the following binding error:
System.Windows.Data Error: 40 : BindingExpression path error: 'L1Setup' property not found on 'object' ''L1SetupViewerCellControl' (Name='')'. BindingExpression:Path=L1Setup.EnPor1OutDia; DataItem='L1SetupViewerCellControl' (Name=''); target element is 'L1SetupViewerCellControl' (Name=''); target property is 'Value' (type 'String')
I tried several answers on stackOverflow, nothing worked for me and i don't get it whats wrong.
Setting this.DataContext = this on the L1SetupViewerEntrySectionView breaks the inheritance of the data context from L1SetupViewerView and that's why the binding to L1Setup fails.
Instead of explicitly setting the DataContext in the code-behind, you should either set the DataContext of the root element in UserControl like this:
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}>
...or the source on each binding:
<uc:L1SetupViewerCellControl ...
Value="{Binding Setup.EnOveSpd, RelativeSource={RelativeSource AncestorType=UserControl}}" />
The very same thing applies to the L1SetupViewerCellControl, i.e. remove this.DataContext = this from the constructor and bind to the Value property using a RelativeSource:
<TextBox Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" />
This question already has answers here:
How do I get INotifyPropertyChanged to update bound items from a list stored in SQL?
(1 answer)
C# WPF ViewModel for a class with List
(1 answer)
Closed 3 years ago.
I'm making an application in WPF and wanted to bind a List<string> to an ItemsControl using a DataTemplate. However, when I try to Add elements to the list, the changes aren't reflected in my interface.
I've tried searching for answers relating to collections and dependency properties, but no one seems to even acknowledge that this is a problem. The documentation on Microsoft's websites don't provide any help either.
public partial class MainWindow : Window {
public static readonly DependencyProperty PathsProperty = DependencyProperty.Register(
"Paths",
typeof(List<string>),
typeof(MainWindow),
new PropertyMetadata(new List<string>())
);
public IList<string> Paths {
get { return GetValue(PhotoPathsProperty) as IList<string>; }
set { SetValue(PhotoPathsProperty, value); }
}
public MainWindow() {
DataContext = this;
InitializeComponent();
WatermarkPath = "filepath";
PhotoPaths = new List<string>();
}
private void Button_Click_1(object sender, RoutedEventArgs e) {
OpenFileDialog dialog = new OpenFileDialog {
Filter = ".PNG|*.png|.JPG|*.jpg",
Title = "Open Photo Image(s)"
};
if (dialog.ShowDialog() == true) {
foreach (var path in dialog.FileNames) {
PhotoPaths.Add(path);
}
}
}
}
<Window x:Class="PE_WaterMarker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PE_WaterMarker"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<GroupBox x:Name="groupBox" DockPanel.Dock="Top" Header="Watermark" Margin="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="textBox" Grid.Column="0" Text="{Binding Path=WatermarkPath}" VerticalAlignment="Center"/>
<Button x:Name="button" Grid.Column="1" Content="Browse" Click="Button_Click" VerticalAlignment="Center"/>
</Grid>
</GroupBox>
<GroupBox Header="Images">
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=Paths}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding Path=.}"/>
<Button Grid.Column="1" Content="Browse"/>
<Button Grid.Column="2" Content="Remove"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Add Image(s)" Click="Button_Click_1"/>
</StackPanel>
</GroupBox>
</DockPanel>
</Window>
This is my first time writing here. I though my first question would by more complex but I am tired of searching for an answer.
I just started with WPF (MVVM), here it goes:
I have 3 user Controls in a Page, the three of them are the same class of Control. The important thing here is that in the first TextBox, when it lost focus, it calls a method to calculate the last TextBox.Text.
<UserControl x:Class="ASSEMBLY.View.UserControls.EtiquetaDinamicaUserControl"
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:ASSEMBLY.View.UserControls"
x:Name="userControl"
mc:Ignorable="d"
Background="Orange" BorderThickness="0" >
<DockPanel VerticalAlignment="Stretch">
<Grid Background="green">
<Grid.ColumnDefinitions >
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox Grid.Column="0" VerticalAlignment="Stretch" Stretch="Fill" >
<Label Grid.Column="0" Content="{Binding NombreEtiqueta, ElementName=userControl, Mode=TwoWay}" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0,0,5,0"
Background="White" VerticalAlignment="Stretch" />
</Viewbox>
<Viewbox Grid.Column="1" VerticalAlignment="Stretch" Stretch="Fill" >
<TextBox Grid.Column="1" MinWidth="30" BorderThickness="0" Margin="0,0,5,0"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left" LostFocus="IdChanged" Loaded="IdChanged"
Text="{Binding IdValue, ElementName=userControl, Mode=TwoWay}"
/>
</Viewbox>
<Viewbox Grid.Column="2" VerticalAlignment="Stretch" Stretch="Fill" >
<TextBox Grid.Row="0" HorizontalAlignment="Stretch" IsEnabled="True" MinWidth="100" BorderThickness="0"
TextAlignment="Left" VerticalAlignment="Stretch"
Text="{Binding Path= Descripcion, ElementName=userControl, Mode=TwoWay}">
</TextBox>
</Viewbox>
</Grid>
</DockPanel>
I have 3 times the same control in the Page, now I need that when the UserControl2 fires LostFocus also fire the LostFocus of the usercontrol3.
<controls:EtiquetaDinamicaUserControl Grid.Row="0" Grid.Column="0" Margin="5,2,0,0" IdValue="{Binding Codempresa1, Mode=TwoWay}" NombreEtiqueta="TEST1"/>
<controls:EtiquetaDinamicaUserControl x:Name="UserControl2" Grid.Row="1" Grid.Column="0" Margin="5,2,0,0" IdValue="{Binding Codempresa2, Mode=TwoWay}" NombreEtiqueta="TEST2"/>
<controls:EtiquetaDinamicaUserControl x:Name="UserControl3" Grid.Row="2" Grid.Column="0" Margin="5,2,0,2" IdValue="{Binding Codempresa3, Mode=TwoWay}" NombreEtiqueta="TEST3"/>
I searched everywhere for something similar, but I found eventrigger (not working because I am not changing a property), interaction (no success trying it).
It works if I set the TextChangedproperty instead of Lostfocus because everything it's bound, but I don't want to be calculating the second textbox every character the user input.
Sorry for my english mistakes and thank you for your help
EDITED. IN ORDER TO HELP I COPY THE CODE BEHIND OF THE USERCONTROL AND THE MVVM PART OF THE VIEW.
USERCONTROL CODE BEHIND:
public static readonly DependencyProperty nombreEtiqueta =
DependencyProperty.Register("NombreEtiqueta", typeof(string), typeof(EtiquetaDinamicaUserControl), new
PropertyMetadata("DEF"));
public string NombreEtiqueta
{
get { return (string)GetValue(nombreEtiqueta); }
set { SetValue(nombreEtiqueta, value); }
}
public static readonly DependencyProperty SetDescripcionProperty =
DependencyProperty.Register("Descripcion", typeof(string), typeof(EtiquetaDinamicaUserControl), new
PropertyMetadata("SIN ASIGNAR"));
public string Descripcion
{
get { return (string)GetValue(SetDescripcionProperty); }
set { SetValue(SetDescripcionProperty, value); }
}
public static DependencyProperty SetIdValueProperty =
DependencyProperty.Register("IdValue", typeof(string), typeof(EtiquetaDinamicaUserControl), new
PropertyMetadata("0"));
public string IdValue
{
get { return (string)GetValue(SetIdValueProperty); }
set { SetValue(SetIdValueProperty, value);
}
}
#region Evento al perder foco IdValue
private void IdChanged(object sender, RoutedEventArgs e)
{
try
{
int tmp_id = Convert.ToInt32(((TextBox)e.Source).Text);
if (tmp_id != 0)
{
Descripcion = tmp_id.ToString();
}
}
catch
{
Descripcion = "SOLO NUMEROS";
}
}
#endregion
MVVM from the View
class PaginaReservaViewModel:ViewModelBase
{
Reserva reserva;
#region Atributos Agencias
private int codempresa1;
private int codempresa2;
private int codempresa3;
#endregion
#region Get/Set Agencias
public int Codempresa1 { get { return codempresa1; } set { codempresa1 = value; } }
public int Codempresa2
{
get { return codempresa2; }
set
{
codempresa2 = value;
if (codempresa3 == 0)
{
codempresa3 = codempresa2;
OnPropertyChanged("Codempresa3");
}
}
}
public int Codempresa3 {
get { return codempresa3; }
set {
codempresa3 = value; } }
Can you use UpdateSourceTrigger="LostFocus" in UserControl' TextBox's Text binding? so it wont fire on every key input. Also please try to implement this all with MVVM (Without hooking events in Code Behind), then you will have much control over the operation.
My Suggestion:
In ViewModel implement a way to modify the other values, when changing Codempresa1. You can include a method to calculate them and call the method in set method of Codempressa1 or you can include the method in PropertyChanged handler.
This question already has answers here:
Callback when dependency property recieves xaml change
(2 answers)
Closed 4 years ago.
I have a very simple User Control which displays a waiting animation with a text above:
<UserControl x:Class="VNegoceNET.Controls.PleaseWait"
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:VNegoceNET.Controls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="RootElement" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.RowSpan="3" Background="White" Content="" Opacity="0.8"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center"
Grid.Row="0" FontSize="18" Foreground="Black"
Margin="8" x:Name="Caption" Text="Loading..."/>
<local:SpinningWait Grid.Row="1"/>
</Grid>
</UserControl>
I want to use it like this:
<controls:PleaseWait Text="Jegg Robot"/>
My problem is that it still displays "Loading..." instead of "Jegg Robot", despite my Dependency Property:
public partial class PleaseWait : UserControl
{
public PleaseWait()
{
InitializeComponent();
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(String), typeof(PleaseWait), new PropertyMetadata("Loading in progress..."));
public string Text
{
get => (string)this.GetValue(TextProperty);
set
{
Caption.Text = value;
this.SetValue(TextProperty, value);
}
}
}
What I have missed?
WPF doesn't use common property wrappers for DP (public string Text), it uses SetValue() directly, when property is set from xaml (<controls:PleaseWait Text="Jegg Robot"/>). so code in setter isn't invoked.
What is needed is propertyChangedCallback:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(PleaseWait),
new PropertyMetadata("Loading in progress...", OnTextChanged));
public string Text
{
get => (string)this.GetValue(TextProperty);
set { this.SetValue(TextProperty, value); }
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var c = (PleaseWait) d;
c.Caption.Text = c.Text;
}
Instead of using a PropertyChangedCallback, like ASh mentioned, you can bind the TextProperty of your TextBlock
...
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center"
Grid.Row="0" FontSize="18" Foreground="Black"
Margin="8" x:Name="Caption" Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PleaseWait}}}"/>
...
I'm trying to create a custom combobox that have a list of items, and each item have an add(+) button that is suppose to add that item to a "favorite" list:
XAML:
<UserControl x:Class=ComboBoxWithButton"
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"
mc:Ignorable="d" d:DesignWidth="300" Height="25">
<ComboBox
x:Name="ComboBoxBtn"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="0,0,0,-1"
Width="300"
ItemsSource="{Binding Source, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding Path=Selected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="{Binding}" Width="250" />
<Button Grid.Column="1" Command="{Binding CommandButton}"
CommandParameter="{Binding Path=Selected}">+</Button>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</UserControl>
XAML.CS:
public IEnumerable Source
{
get { return (IEnumerable)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(IEnumerable), typeof(ComboBoxWithButton), new PropertyMetadata(null));
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("CommandButton", typeof(ICommand), typeof(ComboBoxWithButton), new PropertyMetadata(null));
public ICommand CommandButton
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
Then on my main view, using the combobox I have:
<controls:ComboBoxWithButton Source="{Binding AvailableClients}" Selected="{Binding SelectedClient, Mode=TwoWay}"
LostFocus="OnClientSelected"
CommandButton="{Binding AddFavoriteCommand}"/>
And:
AddFavoriteCommand = new RelayCommand<object>(AddToFavorite, f => true);
But it's not triggering my function "AddToFavorite"
The button is inside a DataTemplate, so each button's DataContext is different than the UserControl's DataContext.
You need to change the Command binding to access the UserControl's DataContext:
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="{Binding}" Width="250" />
<Button Grid.Column="1" Command="{Binding CommandButton, RelativeSource={RelativeSource AncestorType=UserControl}}"
CommandParameter="{Binding Path=Selected}">+</Button>
</Grid>
</DataTemplate>