Updating custom control - c#

I have custom ComboBox control which allows to pick colors, like described in this article Color Picker using WPF Combobox.
I insert custom ComboBox in MainWindow this way:
<local:Colorpicker x:Name="brushesComboBox"></local:Colorpicker>
When I select colors manually, it works fine, but if I set the color programmatically like that:
brushesComboBox.SelectedColor= new SolidColorBrush(Colors.Aquamarine);
ComboBox doesn`t update itself.
I understand that I will need to modify the code of Colorpicker class, so that when dependancy property is set it will force to update selected index in the internal combobox. How do I do that?
Colorpicker class, xaml part:
<UserControl x:Class="WpfParabola.Colorpicker"
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:WpfParabola"
xmlns:sys="clr-namespace:System;assembly=mscorlib" Name="uccolorpicker"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="200">
<UserControl.Resources>
<ResourceDictionary>
<ObjectDataProvider MethodName="GetType"
ObjectType="{x:Type sys:Type}" x:Key="colorsTypeOdp">
<ObjectDataProvider.MethodParameters>
<sys:String>System.Windows.Media.Colors, PresentationCore,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35</sys:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider ObjectInstance="{StaticResource colorsTypeOdp}"
MethodName="GetProperties" x:Key="colorPropertiesOdp">
</ObjectDataProvider>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ComboBox Name="superCombo"
ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}"
SelectedValuePath="Name"
SelectedValue="{Binding ElementName=uccolorpicker,
Path=SelectedColor}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="50" Height="{Binding ElementName=FontSize+4}" Margin="2" Background="{Binding Name}"/>
<TextBlock TextAlignment="Left" VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</UserControl>
Colorpicker class, code behind:
public partial class Colorpicker : UserControl
{
public Colorpicker()
{
InitializeComponent();
superCombo.SelectedIndex = 0;
}
public Brush SelectedColor
{
get { return (Brush)GetValue(SelectedColorProperty); }
set{SetValue(SelectedColorProperty, value);}
}
// Using a DependencyProperty as the backing store for SelectedColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register("SelectedColor", typeof(Brush), typeof(Colorpicker), new UIPropertyMetadata(null));
}

You can add callback to your dependency property and find the index based on the new Brush value. You can modify your SelectedColorProperty initialization below.
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Brush), typeof(Colorpicker), new PropertyMetadata(default(Brush), OnSelectedColorChanged));
private static void OnSelectedColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var newBrush = (Brush)e.NewValue;
var colorPicker = (Colorpicker)d;
var comboBox = colorPicker.superCombo;
// Find your index here using the new Brush value.
// And update the selected index of your ComboBox.
}

Related

how to Hide buttons in usercontrol from main window?

I have a user control that have a multi buttons and In the application i use this user control on multi windows ,but i want to Collapsed (shown/hidden) some buttons if the user select in the application a window 1 and show same button if the user select in the application a window 2
UserControl
<Grid x:Name="girdBtuWidow" >
<StackPanel Orientation="Horizontal">
<Button Content="add" x:Name="add" Visibility="{Binding window1_Loaded}" x:FieldModifier="public" Height="50" Width="100" Margin="0" Click="add_click" />
<Button Content="show history" x:Name="Personal" Height="50" Width="100" Margin="0" />
<Button Content="Show Customer" x:Name="Customer" Height="50" Width="100" Margin="0" />
</StackPanel>
</Grid>
how to set the property (Visibility) of button in the User Control from the application window ?
You don't need to use a Window_Loaded Event here.
You need to expose a Visibility property for each of your buttons in your UserControls.
In your UserControl add a binding to each button for the Visibility property:
Visibility="{Binding AddButtonVisibility}"
Visibility="{Binding ShowHistoryButtonVisibility}"
Visibility="{Binding ShowCustomerButtonVisibility}"
Make sure you add a DataContext to your UserControl, I generally use Self:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
In your UserControl Code Behind add Dependency Properties for each of the Bindings above:
public Visibility AddButtonVisibility
{
get { return (Visibility)GetValue(AddButtonVisibilityProperty); }
set { SetValue(AddButtonVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for AddButtonVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddButtonVisibilityProperty =
DependencyProperty.Register("AddButtonVisibility", typeof(Visibility), typeof(UserControl1), new PropertyMetadata(Visibility.Visible));
public Visibility ShowHistoryButtonVisibility
{
get { return (Visibility)GetValue(ShowHistoryButtonVisibilityProperty); }
set { SetValue(ShowHistoryButtonVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for ShowHistoryButtonVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ShowHistoryButtonVisibilityProperty =
DependencyProperty.Register("ShowHistoryButtonVisibility", typeof(Visibility), typeof(UserControl1), new PropertyMetadata(Visibility.Visible));
public Visibility ShowCustomerButtonVisibility
{
get { return (Visibility)GetValue(ShowCustomerButtonVisibilityProperty); }
set { SetValue(ShowCustomerButtonVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for ShowCustomerButtonVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ShowCustomerButtonVisibilityProperty =
DependencyProperty.Register("ShowCustomerButtonVisibility", typeof(Visibility), typeof(UserControl1), new PropertyMetadata(Visibility.Visible));
In Visual Studio, There is a code snippet shortcut for Dependency Properties - type propdp and hit tab twice.
Now, to use the properties you have just created put the Usercontrol onto the relevant window:
<local:UserControl1 AddButtonVisibility="Collapsed" />
local is the project namespaces' alias - defined at the top of your Window. You can just drag and drop the UserControl onto your window, and it will do this for you. (You may need to rebuild in order to see your UserControls in your Toolbox.
You should now see your control with the Add Button collapsed.
For completeness sake, here is the XAML side of things:
UserControl Xaml:
<UserControl x:Class="WpfApplication2.UserControl1"
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:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid x:Name="girdBtuWidow" >
<StackPanel Orientation="Horizontal">
<Button Content="Add" x:Name="add" Height="50" Width="100" Margin="0" Click="Add_Click" Visibility="{Binding AddButtonVisibility}"/>
<Button Content="Show History" x:Name="Personal" Height="50" Width="100" Margin="0" Click="ShowHistory_Click" Visibility="{Binding ShowHistoryButtonVisibility}" />
<Button Content="Show Customer" x:Name="Customer" Height="50" Width="100" Margin="0" Click="ShowCustomer_Click" Visibility="{Binding ShowCustomerButtonVisibility}"/>
</StackPanel>
</Grid>
Window1.Xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2" x:Class="WpfApplication2.Window1"
Title="Window1" Height="300" Width="308">
<Grid>
<local:UserControl1 HorizontalAlignment="Left" VerticalAlignment="Top" AddButtonVisibility="Collapsed" />
</Grid>
public static readonly DependencyProperty onBackVisibilityProperty =
DependencyProperty.Register("onBackVisibility", typeof(Visibility), typeof(MyToolBar), new PropertyMetadata(Visibility.Visible));
public Visibility onBackVisibility
{
get { return (Visibility)GetValue(onBackVisibilityProperty); }
set { SetValue(onBackVisibilityProperty, value); }
}
public static readonly DependencyProperty onBackVisibilityProperty =
DependencyProperty.Register("onBackVisibility", typeof(Visibility), typeof(MyToolBar), new PropertyMetadata(Visibility.Visible));
public Visibility onBackVisibility
{
get { return (Visibility)GetValue(onBackVisibilityProperty); }
set { SetValue(onBackVisibilityProperty, value); }
}
//After this goto xaml
Button Name="tbrBack"
ToolTip="{DynamicResource Back}"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Click="tbrBack_Click"
Visibility="{Binding onBackVisibility ,ElementName = usercontrol}

How to raise event at Mainwindow

I have usercontrol which has datagrid .This usercontrol is added to WPF main window.I am handling gridrow selection changed event through bubble event.
<ListBox x:Name="myListBox" Grid.Row="0"
ItemsSource="{Binding Path=_myControl}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding CurrentItem}" SelectedIndex="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<local:UCSearchEntity GridRowSelectionConfirmed="{Binding Path=UCSearchEntity_GridRowSelectionConfirmed}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
public class MyViewModel:INotifyPropertyChanged
{
}
the error is Provide value on 'System.Windows.Data.Binding' threw an exception.
How can I access this usercontrol event in my mainwindow viewModel ?
You cannot do binding to events like that you have to do something like this on your mainwindow :
<Window DataGrid.GridRowSelectionConfirmed="GridRowSelectionConfirmed">
and GridRowSelectionConfirmed would be a method in your mainwindow
And the xaml above is a snippet in your xaml of the mainwindow.
If you want to stick to using MVVM then you have to start using behaviours but this is a more advanced concept. The behaviour is needed to attach a command that you can databind to an event that otherwise is not bindable like you were trying to do. You see I am making use of interactivity, if you want to do the same you need the blend sdk. An example :
public class AddingNewItemBehavior : Behavior<DataGrid>
{
public static readonly DependencyProperty CommandProperty
= DependencyProperty.Register("Command", typeof(ICommand), typeof(AddingNewItemBehavior), new PropertyMetadata());
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.AddingNewItem += AssociatedObject_OnAddingNewItem;
}
private void AssociatedObject_OnAddingNewItem(object sender, AddingNewItemEventArgs addingNewItemEventArgs)
{
AddingNewItem addingNewItem = new AddingNewItem();
Command.Execute(addingNewItem);
addingNewItemEventArgs.NewItem = addingNewItem.NewItem;
}
}
This is an adding new behaviour I have on a datagrid.
And this is a simplified example where i make use of that behaviour :
<UserControl x:Class="Interstone.Configuratie.Views.GraveerFiguurAdminUserControl"
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:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:iCeTechControlLibrary="clr-namespace:ICeTechControlLibrary;assembly=ICeTechControlLibrary"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<DataGrid ItemsSource="{Binding ZandstraalImageTypes.View}" AutoGenerateColumns="False"
VerticalGridLinesBrush="#FFC9CACA" HorizontalGridLinesBrush="#FFC9CACA" RowHeaderWidth="50"
>
<i:Interaction.Behaviors>
<iCeTechControlLibrary:AddingNewItemBehavior Command="{Binding AddingNewCommand}"/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="Categorie" Binding="{Binding TypeNaam}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</Grid>

wpf binding text inside usercontrol text box from main window text box

main window
<TextBox x:Name="fbSearchBox" Margin="69,10,298,11" TextWrapping="Wrap" BorderBrush=" x:Null}"/>
<local:FacebookAutoComplete "want to set text from here of fbSearchBox" />
user control
<UserControl x:Class="ZuneWithCtrls.Pages.Facebook.Home.FacebookAutoComplete"
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:DesignHeight="300" d:DesignWidth="300" Width="431" Height="49"
x:Name="uc">
<TextBlock x:Name="txtDynamicText"/>
</UserControl>
want to show text in txtdynamicText when type from fbSearchBox.. Plz help
You need some property in user control you can bind to.
Add a dependency property to your user control:
public static readonly DependencyProperty DynamicTextProperty =
DependencyProperty.Register(
"DynamicText",
typeof(string),
typeof(FacebookAutoComplete),
new FrameworkPropertyMetadata(null));
public string DynamicText
{
get { return (string)GetValue(DynamicTextProperty); }
set { SetValue(DynamicTextProperty, value); }
}
Bind a nested control inside user control to this dependency property:
<TextBlock x:Name="txtDynamicText"
Text="{Binding Path=DynamicText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
Now you can bind FacebookAutoComplete.DynamicText to the TextBox from MainWindow:
<local:FacebookAutoComplete DynamicText="{Binding Text, ElementName=fbSearchBox, UpdateSourceTrigger=PropertyChanged}"/>

Binding to a userControl which contains custom control

I want to use the ToggleSwitch control of the WPF Spark project
So I created a UserControl which contains a ToggleSwitch control and configures it (color, size, etc).
<UserControl x:Class="WpfControls.ToggleSwitch.MyToggleSwitchControl"
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:toggleSwitch="clr-namespace:WpfControls.ToggleSwitch"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/WpfControls;component/ToggleSwitch/ToggleSwitch.Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<toggleSwitch:ToggleSwitch x:Name="Toggle"
Width="54"
Height="21"
Margin="0"
Background="Black"
BorderThickness="2"
CheckedForeground="White"
CheckedText="Yes"
CheckedToolTip=""
CornerRadius="10"
FontFamily="Tahoma"
FontSize="10"
FontWeight="Normal"
IsCheckedLeft="False"
Padding="0"
ThumbBorderThickness="2"
ThumbCornerRadius="21"
ThumbGlowColor="Gray"
ThumbShineCornerRadius="20,20,0,0"
ThumbWidth="35"
UncheckedForeground="Black"
UncheckedText="No"
UncheckedToolTip="No">
</toggleSwitch:ToggleSwitch>
</Grid>
</UserControl>
The ToggleSwitch is a CustomControl which overrides the standard WPF ToggleButton.
Now I want to use the ToggleButton property IsChecked in my XAML for Binding.
<toggleSwitch:MyToggleSwitchControl IsChecked="{Binding IsChecked}" />
How can I achieve that?
Create in code-behind DependencyProperty:
public bool IsToggleChecked
{
get { return (bool)GetValue(IsToggleCheckedProperty); }
set { SetValue(IsToggleCheckedProperty, value); }
}
public static readonly DependencyProperty IsToggleCheckedProperty =
DependencyProperty.Register("IsToggleChecked", typeof(bool), typeof(MyToggleSwitchControl), new PropertyMetadata(false));
and bind it to IsChecked property of your ToggleSwitch:
<toggleSwitch:ToggleSwitch IsChecked="{Binding RelativeSource={RelativeSource AncestorLevel=1,AncestorType=UserControl,Mode=FindAncestor}, Path=IsToggleChecked}"
After doing this you'll be able to do:
<toggleSwitch:MyToggleSwitchControl IsToggleChecked="{Binding IsChecked}" />
You could use an dependency property.
In your custom control add a dependency property like this:
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool),
typeof(MyToggleSwitchControl), null);
// .NET Property wrapper
public bool IsChecked
{
get
{
return (bool)GetValue(IsCheckedProperty);
}
set { SetValue(IsCheckedProperty, value); }
}

Why does my Custom UserControl's dependency property not work with dynamically binding?

My Custom UserControl's dependency property will bind correctly if the value is statically defined in the XAML calling it, like this:
TextBoxText="myName"
but not if the value is bound dynamically itself:
TextBoxText="{Binding ItemTypeIdCode}"
There is my full Code.
Custom UserControl XAML:
<UserControl
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"
mc:Ignorable="d"
x:Class="TestUserControl.UserControl1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
x:Name="UserControl" Height="22" Width="282">
<Grid x:Name="LayoutRoot">
<TextBlock TextWrapping="Wrap" Text="{Binding MyName, ElementName=LayoutRoot}"/>
</Grid>
Custom UserControl Code:
public static readonly DependencyProperty TextBoxTextProperty =DependencyProperty.Register("TextBoxText", typeof(string), typeof(UserControl1));
public string TextBoxText
{
get { return (string)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
In my Main Window XAML :
<Grid x:Name="LayoutRoot">
<Button Content="Button" Height="78" Margin="0,0,93,112" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="94" Click="MyButtonClick"/>
<ListBox x:Name="MyListBox" HorizontalAlignment="Left" Margin="8,8,0,112" Width="192">
<ListBox.ItemTemplate>
<DataTemplate>
<local:UserControl1 HorizontalAlignment="Stretch" Margin="286,37,56,0" VerticalAlignment="Top" d:LayoutOverrides="Height" TextBoxText="{Binding MyName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In my Main Window Code :
private void MyButtonClick(object sender, System.Windows.RoutedEventArgs e)
{
List<string> MyName = new List<string>();
MyName.Add("Name 1");
MyName.Add("Name 2");
MyName.Add("Name 3");
MyListBox.ItemsSource = MyName;
}
This Code Successfully add my Custom UserControl as ListBoxItem in ListBox But Problem it is not display any text which i Binding.
I don`t understand where i am doing wrong.
You set the DataContext of the UserControl to itself, all bindings will then try to find the path on the UserControl, that is why you should not set the DataContext on UserControls.
You should see a binding error in the Output window of Visual Studio saying something like:
System.Windows.Data Error: 40 : BindingExpression path error: 'ItemTypeIdCode' property not found on 'object' ''UserControl1' (Name='UserControl')'. ...

Categories