- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 14090
Idea was to have one rectangle and on button click do hide / show that rectangle. Easiest way is with BooleanToVisibilityConverter.
XAML looks like this:
<Window x:Class="BooleanToVisibilityConverterExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModel="clr-namespace:BooleanToVisibilityConverterExample.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <viewModel:BooleanToVisibilityConverterExampleViewModel x:Key="BooleanToVisibilityConverterExampleViewModel" />
            <BooleanToVisibilityConverter x:Key="BoolToVis" />
        </Grid.Resources>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>
        
        <Button DataContext="{StaticResource BooleanToVisibilityConverterExampleViewModel}" Command="{Binding OnClick}" Grid.Row="1" Content="Click Me!" VerticalContentAlignment="Bottom"/>
        <Rectangle x:Name="greenLine"
                    Height="25"
                    Width="25"
                    DataContext="{StaticResource BooleanToVisibilityConverterExampleViewModel}"
                    Visibility="{Binding MyHidden, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"
                    Fill="Green"/>
    </Grid>
</Window>
Note how I declared resource:
<BooleanToVisibilityConverter x:Key="BoolToVis" />
After that in rectangle declaration note:
Visibility="{Binding MyHidden, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"
There is no too much philosophy about code itself, basically everything is happening here:
MyHidden = !MyHidden;
 OnPropertyChanged("MyHidden");
Property changed I explained here.
Example you can download from here.
There is also another solution, which I will not explain, since it is a bit more complicated, you have to implement IValueConverter, example for that version you can download from here, and to write that example I was this web site.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 5390
Idea was to write small app which will have one combo box where user will be able to change template for some list of buttons.
Instead I just made one project where I merged knowledge from this, this, this, and this article.
That is just for my future reference. Example project you can download from here.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 6381
Now idea is to have one control inside ItemsControl, and everything that inside UserControl, something like:
<UserControl x:Class="MyUserControl.myControl"
             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">
    <Grid>
      
      <ItemsControl ItemsSource="{Binding myLabels}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <Label Content="{Binding DataContext.myContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
      </ItemsControl>
      
    </Grid>
</UserControl>
Here notice line:
<Label Content="{Binding DataContext.myContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
This line was taken from here.
My MainWindow.xaml looks like this:
<Window x:Class="UserControlDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myUserControl="clr-namespace:MyUserControl;assembly=MyUserControl"
        xmlns:viewModel="clr-namespace:UserControlDataContext.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
      
        <Grid.Resources>
          <viewModel:UserControlDataContextViewModel x:Key="UserControlDataContextViewModel" />
        </Grid.Resources>
      
        <myUserControl:myControl DataContext="{Binding Source={StaticResource UserControlDataContextViewModel}}"/>
      
    </Grid>
</Window>
and view model like:
public class UserControlDataContextViewModel
{
	public string myContent { get; set; }
	public IEnumerable<string> myLabels { get; set; }
	public UserControlDataContextViewModel()
	{
		myContent = "test";
		myLabels = new[] { "test1", "test2" };
	}
}
Example project you can download from here.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 6698
In this article I want to extend my ItemsControl.Style, by binding template.
XAML:
<Grid>
	<Grid.Resources>
		<itemsControlItemTemplate:ItemsControlViewModel x:Key="ItemsControlViewModel" />
	</Grid.Resources>
	<ItemsControl DataContext="{StaticResource ItemsControlViewModel}" ItemsSource="{Binding myItemsSource}">
		<ItemsControl.Style>
			<Style TargetType="ItemsControl">
				<Style.Triggers>
					<DataTrigger Binding="{Binding ParentMyItemType}" Value="{x:Static itemsControlItemTemplate:myItemTypes.WrapPanel}">
						<Setter Property="ItemsPanel">
							<Setter.Value>
								<ItemsPanelTemplate>
									<WrapPanel />
								</ItemsPanelTemplate>
							</Setter.Value>
						</Setter>
					</DataTrigger>
					<DataTrigger Binding="{Binding ParentMyItemType}" Value="{x:Static itemsControlItemTemplate:myItemTypes.StackPanel}">
						<Setter Property="ItemsPanel">
							<Setter.Value>
								<ItemsPanelTemplate>
									<StackPanel />
								</ItemsPanelTemplate>
							</Setter.Value>
						</Setter>
					</DataTrigger>
				</Style.Triggers>
			</Style>
		</ItemsControl.Style>
		<ItemsControl.ItemTemplate>
			<DataTemplate>
			
				<DataTemplate.Resources>
					<itemsControlItemTemplate:AnotherModel x:Key="AnotherModel" />
				</DataTemplate.Resources>
				<Label DataContext="{StaticResource AnotherModel}" Content="{Binding myContent}" />
			</DataTemplate>
		</ItemsControl.ItemTemplate>
	</ItemsControl>
</Grid>
Here notice part, for example:
<DataTrigger Binding="{Binding ParentMyItemType}" Value="{x:Static itemsControlItemTemplate:myItemTypes.WrapPanel}">
	<Setter Property="ItemsPanel">
		<Setter.Value>
			<ItemsPanelTemplate>
				<WrapPanel />
			</ItemsPanelTemplate>
		</Setter.Value>
	</Setter>
</DataTrigger>
Where myItemTypes.WrapPanel I declared something like:
public enum myItemTypes
{
	WrapPanel,
	StackPanel
}
and then my view model looks like:
public class ItemsControlViewModel
{
	public IEnumerable<string> myItemsSource { get; set; }
	public myItemTypes ParentMyItemType { get; set; }
	public ItemsControlViewModel()
	{
		myItemsSource = new[] { "Test1", "Test2" };
		this.ParentMyItemType = myItemTypes.WrapPanel;
	}
}
public class AnotherModel
{
	public string myContent { get; set; }
	public AnotherModel()
	{
		myContent = "test2";
	}
}
notice line:
this.ParentMyItemType = myItemTypes.WrapPanel;
with that line I said that I want my style to be with StackPanel.
Example code you can download from here.