Binding Label to ItemsControl - wpf

I am having trouble working out how to bind the content of a label to the default (ToString()) value of ItemsControl object.
The ItemsControl element is bound to
stepList.ItemsSource = steps;
The steps object is
private var steps = new ObservableCollection<Action>();
<ItemsControl Name="stepList" Margin="10,2,10,10">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1" Margin="0,2,0,2" DockPanel.Dock="Top">
<DockPanel Margin="0,2,0,2">
<DockPanel Width="106" HorizontalAlignment="Right" DockPanel.Dock="Right">
<Button DockPanel.Dock="Right" Click="_deleteStep" Width="22" Margin="0,0,10,0">
<Image Source="resources\icons\delete-bin.png" />
</Button>
<Button DockPanel.Dock="Right" Click="_editStep" Width="22" Margin="0,0,2,0">
<Image Source="resources\icons\edit.png" />
</Button>
<Button DockPanel.Dock="Right" Click="_moveDown" Width="22" Margin="0,0,2,0">
<Image Source="resources\icons\down.png" />
</Button>
<Button DockPanel.Dock="Right" Click="_moveUp" Width="22" Margin="0,0,2,0">
<Image Source="resources\icons\up.png" />
</Button>
</DockPanel>
<DockPanel DockPanel.Dock="Left">
<Label HorizontalAlignment="Stretch" Margin="10,0,0,0" Content="{????}"/>
</DockPanel>
</DockPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Figured it out!
Content="{Binding BindsDirectlyToSource=True}

Related

Label foreground in toolbar

I have a toolbar in my WPF window as shown in bellow, please help me change labels foreground color dynamically in code behind.
Thanks...
<DockPanel Height="60" VerticalAlignment="Top">
<ToolBar Name="MyToolBar" DockPanel.Dock="Top" Height="60" VerticalAlignment="Top" FlowDirection="RightToLeft"
FontFamily="Calibri" FontSize="16" FontWeight="Bold" Background="#FFEEF5FD" Foreground="Black" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<Button Name="BtnSubmit" Style="{DynamicResource TStyle}" Click="BtnSubmit_Click" Tag="New" Height="52" Width="60"
IsDefault="True" Margin="0,0,0,1">
<StackPanel Margin="0" Height="54"
<Image Source="/Img/Save 04.png" Height="25" Margin="16,0"/>
<Label Content="Save" Margin="0,0,0,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button Name="BtnApply" Style="{DynamicResource TStyle}" Click="BtnApply_Click" Tag="New" Height="52"
IsDefault="True" Margin="0,1,0,2" Width="85">
<StackPanel Margin="0" Height="52" Width="82">
<Image Source="/Img/ApplyIcon.png" Height="25" Margin="29,0,26,0"/>
<Label Content="Edit" Margin="-15,0,-23,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</Button>
</ToolBar>
</DockPanel>
To change the Foreground of all TextBlock elements you must define a Brush resource and assign it to all relevant TextBlock elements using {DynamicResource}:
MainWindow.xaml
<Window>
<Window.Resources>
<SolidColorBrush x:Key="ButtonLabelForegroundBrush" Color="Black" />
</Window.Resources>
<DockPanel>
<ToolBar>
<Button>
<TextBlock Foreground="{DynamicResource ButtonLabelForegroundBrush}" />
</Button>
</ToolBar>
</DockPanel>
</Window>
MainWindow.xaml.cs
private void ChangeTextBlockForeground()
{
var brush = FindResource("ButtonLabelForegroundBrush") as SolidColorBrush;
brush.Color = Colors.Red;
}

How to bind a Command to ItemsControl's template

I have to create an ItemsControl like below and a view model with a clickcommand. How can I bind the command to its template?
<ItemsControl Name="connStatusList" HorizontalAlignment="Left" VerticalAlignment="Top" Background="#e0e0e0" Margin="0,0,0,0" MinHeight="325" Width="1700" ItemsSource="{Binding }" >
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border>
<ItemsPresenter/>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Name="wp" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal" Background="#ededed" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel Width="135" Height="160" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,1,0,0" >
<WrapPanel Background="{StaticResource connRectangle}" Width="133" Height="128">
<Image Source="{Binding WifiImage}" Width="70" Height="53" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,2,0,0"/>
<Image Source="{Binding ConnectedImage}" Width="43" Height="63" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="45,7,0,0" />
</WrapPanel>
<WrapPanel>
<Label Content="{Binding ItemNO}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="35,0,0,0" FontWeight="Bold" FontSize="18"></Label>
<Label Content="{Binding Connected}" Name="lblconnected" Visibility="Collapsed"></Label>
</WrapPanel>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
As you are essentially creating a list of buttons, use a Button in your template to bind the command. I assume your command property is called ClickCommand. You might need to adapt the style of the button e.g. in mouse-over state to fit your application.
<DataTemplate>
<Button Command="{Binding ClickCommand}">
<Button.Content>
<WrapPanel Width="135" Height="160" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,1,0,0" >
<WrapPanel Background="{StaticResource connRectangle}" Width="133" Height="128">
<Image Source="{Binding WifiImage}" Width="70" Height="53" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,2,0,0"/>
<Image Source="{Binding ConnectedImage}" Width="43" Height="63" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="45,7,0,0" />
</WrapPanel>
<WrapPanel>
<Label Content="{Binding ItemNO}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="35,0,0,0" FontWeight="Bold" FontSize="18"></Label>
<Label Content="{Binding Connected}" Name="lblconnected" Visibility="Collapsed"></Label>
</WrapPanel>
</WrapPanel>
</Button.Content>
</Button>
</DataTemplate>
Alternatively, you could use an event trigger from the Microsoft.Xaml.Behaviors.Wpf NuGet package. With this approach, the ClickCommand is invoked on mouse button up, it does not change any style.
<DataTemplate>
<WrapPanel Width="135" Height="160" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,1,0,0">
<b:Interaction.Triggers>
<b:EventTrigger EventName="MouseLeftButtonUp">
<b:InvokeCommandAction Command="{Binding ClickCommand}"/>
</b:EventTrigger>
</b:Interaction.Triggers>
<WrapPanel Background="{StaticResource connRectangle}" Width="133" Height="128">
<Image Source="{Binding WifiImage}" Width="70" Height="53" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="35,2,0,0"/>
<Image Source="{Binding ConnectedImage}" Width="43" Height="63" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="45,7,0,0" />
</WrapPanel>
<WrapPanel>
<Label Content="{Binding ItemNO}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="35,0,0,0" FontWeight="Bold" FontSize="18"></Label>
<Label Content="{Binding Connected}" Name="lblconnected" Visibility="Collapsed"></Label>
</WrapPanel>
</WrapPanel>
</DataTemplate>

Adding Scrollbar to ItemsControl

I have a long list coming from my Business logic which I need to display on the UI. As the list is long, I tried adding Scrollviewer but I am unable to scroll.
please find the XAML code below
<Grid Margin="0,32,0,0">
<TextBlock Text="{Binding IDC_WiFi, Source={StaticResource Resources}}" FontFamily="Segoe UI" FontSize="20" Foreground="#4cb5ab" HorizontalAlignment="Left" />
<Button Command="{Binding HardwareWifiAccordionCommand}" BorderThickness="0" Width="16" HorizontalAlignment="Right" Height="16" >
<Button.Background>
<ImageBrush ImageSource="{Binding AccordionImageHardwareWifi}" />
</Button.Background>
</Button>
</Grid>
<TextBlock Text="Klein's, Anil's" FontFamily="Segoe UI" FontSize="15" Foreground="#8fa3ad"/>
<StackPanel Height="200" Visibility="{Binding IsAccordionHardwareWifi, Converter={StaticResource Bool2Visible}}">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding WifiList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,32,0,0">
<Grid>
<Image Source="/Images/Assets/da_wifi1_16x16.png" Height="16" Width="16" HorizontalAlignment="Left" />
<TextBlock Margin="25,0,0,0" Text="{Binding NetworkName}" FontSize="15" Foreground="#FFFFFF" />
<TextBlock Text="" FontSize="15" Foreground="#8fa3ad" HorizontalAlignment="Right" />
</Grid>
<TextBlock Text="" FontSize="15" Foreground="#8fa3ad" HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
Put it into a ScrollViewer.
<ScrollViewer>
<StackPanel >
</StackPanel>
</ScrollViewer>
As #StepUp points out you can just wrap it with a ScrollViewer but I believe this breaks virtualization. That's outside the scope of this question of course but it's something to keep in mind. If performance is likely to become an issue then I'd suggest implementing this as shown in the answer to this question.
The scrollviewer needed a Height to be set
<Grid Margin="0,32,0,0">
<TextBlock Text="{Binding IDC_WiFi, Source={StaticResource Resources}}" FontFamily="Segoe UI" FontSize="20" Foreground="#4cb5ab" HorizontalAlignment="Left" />
<Button Command="{Binding HardwareWifiAccordionCommand}" BorderThickness="0" Width="16" HorizontalAlignment="Right" Height="16" >
<Button.Background>
<ImageBrush ImageSource="{Binding AccordionImageHardwareWifi}" />
</Button.Background>
</Button>
</Grid>
<TextBlock Text="Klein's, Anil's" FontFamily="Segoe UI" FontSize="15" Foreground="#8fa3ad"/>
<StackPanel Height="200" Visibility="{Binding IsAccordionHardwareWifi, Converter={StaticResource Bool2Visible}}">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="350">
<ItemsControl ItemsSource="{Binding WifiList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,32,0,0">
<Grid>
<Image Source="/Images/Assets/da_wifi1_16x16.png" Height="16" Width="16" HorizontalAlignment="Left" />
<TextBlock Margin="25,0,0,0" Text="{Binding NetworkName}" FontSize="15" Foreground="#FFFFFF" />
<TextBlock Text="" FontSize="15" Foreground="#8fa3ad" HorizontalAlignment="Right" />
</Grid>
<TextBlock Text="" FontSize="15" Foreground="#8fa3ad" HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>

margin between image and text

In this code I added an image before the button text I'd like to have a space between the image and text but the code I have isn't working.
<Button Height="25"
Width="80"
Margin="5,10,5,10"
Command="{Binding PreviewTemplateCommand}">
<StackPanel Orientation="Horizontal" Height="15" Width="63">
<Image Source="/UILibrary;component/Themes/Default/Images/preview.PNG"
Height="15" Width="15" Margin="0,0,0,0" />
<TextBlock >Preview</TextBlock>
</StackPanel>
</Button>
Hi you have to set the left margin of the textblock. Try this:
<StackPanel Orientation="Horizontal" Height="15" Width="63">
<Image Source="..." Height="15" Width="15" Margin="0,0,0,0" />
<TextBlock Margin="25,0,0,0">Preview</TextBlock>
</StackPanel>

How to get the underlaying viewmodel of a view/region from another view in WPF Prism

I have 3 regions namely Menu,Toolbar and Content. When a module(ie customer) is clicked in Menu view it will navigate to the respective view in content region, after editing the values in the textboxes I need to save that to DB. How to get the underlaying view model of the active view and send to DAL when save button is clicked in Toolbar view?.
Shell.xaml:
<Grid DockPanel.Dock="Left" Width="65" Margin="1">
<Border CornerRadius="1" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" Margin="1" >
<ContentControl Name="menuControl" PrismRegions:RegionManager.RegionName="{x:Static infra:RegionNames.MenuRegion}"/>
</StackPanel>
</Border>
</Grid>
<Grid DockPanel.Dock="Top" Margin="1">
<Border CornerRadius="1" BorderBrush="Black" BorderThickness="1" >
<StackPanel Orientation="Vertical" Margin="2">
<ContentControl Name="toolbarControl" PrismRegions:RegionManager.RegionName="{x:Static infra:RegionNames.ToolbarRegion}"/>
</StackPanel>
</Border>
</Grid>
<Grid DockPanel.Dock="Right" Margin="2">
<Border CornerRadius="1" BorderBrush="Black" BorderThickness="1">
<StackPanel Margin="5" >
<ContentControl Name="contentControl" DockPanel.Dock="Top" PrismRegions:RegionManager.RegionName="{x:Static infra:RegionNames.ContentRegion}"/>
</StackPanel>
</Border>
</Grid>
Menu.xaml:
<Button Grid.Row="0" Name="btnHome" Background="Transparent" Margin="1" ToolTip="Home" Command="{x:Static inf:ApplicationCommands.NavigationCommand}" CommandParameter="{x:Type mod:HomeView}">
<TextBlock Height="32" Width="32" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/home_32.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Row="1" Name="btnBank" Background="Transparent" Margin="1" ToolTip="Bank" Command="{x:Static inf:ApplicationCommands.NavigationCommand}" CommandParameter="{x:Type mod:BankView}">
<TextBlock Height="32" Width="32" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/bank_64.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Row="2" Name="btnCustomer" Background="Transparent" Margin="1" ToolTip="Customer" Command="{x:Static inf:ApplicationCommands.NavigationCommand}" CommandParameter="{x:Type mod:CustomerView}">
<TextBlock Height="32" Width="32" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/customer_128.ico"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Row="3" Name="btnEmployee" Background="Transparent" Margin="1" ToolTip="Employee" Command="{x:Static inf:ApplicationCommands.NavigationCommand}" CommandParameter="{x:Type mod:EmployeeView}">
<TextBlock Height="32" Width="32" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/employee_128.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
Toolbar.xaml:
<Button Grid.Column="0" Margin="1" Name="btnAdd" Height="35" Width="35" ToolTip="Add" Background="Transparent" Command="{Binding AddCommand}" CommandParameter="Add" >
<TextBlock Height="30" Width="30" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/plus_32.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Column="1" Margin="1" Name="btnEdit" Height="35" Width="35" ToolTip="Edit" Background="Transparent" Command="{Binding EditCommand}" CommandParameter="Edit" >
<TextBlock Height="30" Width="30" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/pencil_32.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Column="2" Margin="1" Name="btnSave" Height="35" Width="35" ToolTip="Save" Background="Transparent" Command="{Binding SaveCommand}" CommandParameter="Save" >
<TextBlock Height="30" Width="30" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/save_32.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
<Button Grid.Column="3" Margin="1" Name="btnPrint" Height="35" Width="35" ToolTip="Print" Background="Transparent" Command="{Binding PrintCommand}" CommandParameter="Print" >
<TextBlock Height="30" Width="30" Text ="">
<TextBlock.Background>
<ImageBrush Stretch="Fill" ImageSource="/Modules;component/Icons/print_32.png"/>
</TextBlock.Background>
</TextBlock>
</Button>
UI Design:
Basically your view's state is entirely present in the viewmodel. In your scenario of Button being out side the viewmodel of the form to save what you can do is:
In tool bar viewmodel:
Raise an event that Save button is clicked
myEventAggregator.RaiseEvent<SaveButtonClicked>().Publish(args);
On viewmodel constructor:
subscribe for the event that you raise when you click on save button in toolbar region
myEventAggregator.GetEvent<SaveButtonClicked>().Subscribe(yourSubscriberDelegate);
On Exit of the form or cancel of form:
Unsubscribe for the event. (this makes sure you don't have multiple active forms saving the data at the same time)
myEventAggregator.GetEvent<SaveButtonClicked>().UnSubscribe(yourSubscriberDelegate);
For this you need Event aggregator knowledge of publish and subscribe. Find more details here

Resources