Visibility of a child Control not working inside parent - wpf

I have a StackPanel inside a Grid which is inside a UserControl. I have set the Visibility of the StackPanel based on a property called ShowInstrumentAction that is present in the ViewModel, which is set as a DataContext. This operation works just fine.
But I have a button inside this StackPanel (please see PrimeFlush3TimesButton) which I want it to be visible based on some other condition. But the child level visibility won't work.
Is it possible to do this kind of binding?
Or should I write a style for Visibility on the button?
I'm not sure what may be the right approach. Please help.
<StackPanel x:Name="InstrumentOperationsPanel" Visibility="{Binding DataContext.ShowInstrumentAction,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Converter={StaticResource boolToVisibility}}" Orientation="Horizontal" Grid.Row="0" HorizontalAlignment="Center">
<Button x:Name="PrimeButton"
Content="{StaticResource InstrumentPrime}"
Margin="{StaticResource AllControlsMargin}" Command="{Binding DataContext.InstrumentPrimeCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}">
</Button>
<Button x:Name="FlushButton"
Content="{StaticResource InstrumentFlush}"
Margin="{StaticResource AllControlsMargin}" Command="{Binding DataContext.InstrumentFlushCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}">
</Button>
<Button x:Name="PrimeFlush3TimesButton"
Content="{StaticResource PrimeAndFlush3Times}"
Margin="{StaticResource AllControlsMargin}"
Visibility="{Binding DataContext.IsBuiltInUser,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl},AncestorLevel=3},Converter={StaticResource boolToVisibility}}"
Command="{Binding DataContext.InstrumentPrimeAndFlush3TimesCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}">
</Button>
</StackPanel>

Use ElementBinding. Name the User Control.
<Button x:Name="PrimeFlush3TimesButton"
Content="{StaticResource PrimeAndFlush3Times}"
Margin="{StaticResource AllControlsMargin}"
Visibility="{Binding ElementName=UserControlName,Path=DataContext.IsBuiltInUser,Converter={StaticResource boolToVisibility}}"
Command="{Binding ElementName=UserControlName,Path=DataContext.InstrumentPrimeAndFlush3TimesCommand}">
</Button>

Related

Should I use a ContextMenu to show a couple of buttons?

I am developing a WPF application and I want the following functionality: If a user right clicks on a progress bar a small context menu should popup at the clicked position. This menu should just contain a couple of buttons which are lined up horizontally. Should I use the ContextMenu for this or are there better suitable WPF elements?
I tried a ContextMenu and this is how it looks like:
This is the XAML:
<ProgressBar x:Name="PgF" Height="10" Value="{Binding Path=FileCurrentMs}" Maximum="{Binding Path=FileLengthMs}">
<ProgressBar.ContextMenu>
<ContextMenu>
<StackPanel Orientation="Horizontal">
<Button Content="A"/>
<Button Content="B"/>
<Button Content="C"/>
</StackPanel>
</ContextMenu>
</ProgressBar.ContextMenu>
</ProgressBar>
In the ContextMenu I have the space to the left and to the right which I don’t want and I read in other posts that it is not simple just to remove this space. Any ideas?
Try like this :
<ProgressBar x:Name="PgF" Height="10" Value="{Binding Path=FileCurrentMs}" Maximum="{Binding Path=FileLengthMs}">
<ProgressBar.ContextMenu>
<ContextMenu>
<MenuItem>
<MenuItem.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="A" Margin="2"/>
<Button Content="B" Margin="2"/>
<Button Content="C" Margin="2"/>
</StackPanel>
</ControlTemplate>
</MenuItem.Template>
</MenuItem>
</ContextMenu>
</ProgressBar.ContextMenu>
</ProgressBar>
You need to put all buttons in a single menu item :) good luck

DataGridTemplateColumn.CellTemplate How to add Image conditionally and hide checkbox in same column cell

<c1:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkBxIsChecked" IsChecked="{Binding IsChecked, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsVisible, Mode=TwoWay}" >
<Image Name="ErrorImage" Visibility ="{Binding IsImgVisible, Mode=TwoWay}" Source= "../../../Resources/Images/Fail.png" Height="16" Width="16" Margin="5,0,0,0"></Image>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<t:MapEventToCommand Command="{Binding Source={StaticResource TestVM},Path=IsCkCommand}" CommandParameter="checked" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<t:MapEventToCommand Command="{Binding Source={StaticResource TestVM},Path=IsCkCommand}" CommandParameter="unchecked" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</c1:DataGridTemplateColumn.CellTemplate>
</c1:DataGridTemplateColumn>
I want to hide a check box in column and display image based on the data from db .
I was trying the above approach , but unable to display the image when i made visibility.collapse for the checkbox .
can i do that from codebehind ? , please suggest me .
Test one record in the attched image i am expecting to display image instead of checkbo ,where as it is showing empty because i made visibility collapsed against the row .
Thanks in advance .
You have added Image as child of CheckBox. So, making parent (CheckBox) collapsed will eventually make child (image) collapsed. Make checkBox and Image as siblings of parent container.
Replace
<CheckBox>
<Image/>
</CheckBox>
with
<Grid>
<CheckBox/>
<Image/>
<Grid>
Assuming Visibility bindings working fine.

MVVM : Binding Commands with Collection to Listbox in WPF

i have a list box in which there are different controls like button , text box etc in its item template, i have a collection which i bind with listbox, it works fine , but now i want to move my code to MVVM , and i write some commands in my View Model for clicks events of buttons , how can i bind my collection + my commands to list box ??? because commands are not in the collection, this is the Data Template for my list Box
<DataTemplate x:Key="listItemTemplate">
<Grid ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Name="commentsPanel" LastChildFill="False" MinWidth="350">
<TextBlock Name="txtUserName" IsEnabled="False" Text="{Binding UserName}"
Width="Auto" DockPanel.Dock="Left" Foreground="GhostWhite" Margin="0,6,0,0"></TextBlock>
<TextBlock Name="txtDate" IsEnabled="False" Text="{Binding CreateDt}"
Width="Auto" DockPanel.Dock="Left" Foreground="Green" Margin="4,6,0,0"></TextBlock>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" Width="{Binding EditPanelWidth}" x:Name="EditDeletePanel" Visibility="{Binding ButtonVisibilityText }">
<Button Name="btnEdit" Content="Edit" Width="Auto" DockPanel.Dock="Right" Height="20"
Click="btnEdit_Click_1" Margin="4,4,0,4" Foreground="GhostWhite" VerticalContentAlignment="Top" Visibility="{Binding ButtonVisibilityText}"></Button>
<Button Name="btnDelete" Content="Delete" Width="Auto" Height="20" VerticalContentAlignment="Top" DockPanel.Dock="Right" Visibility="{Binding ButtonVisibilityText}"
Click="btnDelete_Click_1" Margin="4"></Button>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" x:Name="SaveCancelPanel" Visibility="{Binding CancelSaveEnableText}">
<Button Name="btnSave" Content="Save" Width="Auto" Height="20" DockPanel.Dock="Right"
Click="btnSave_Click_1" Margin="4"></Button>
<Button Name="btnCancel" Content="Cancel" Height="20" Width="Auto" DockPanel.Dock="Right"
Click="btnCancel_Click_1" Margin="4"></Button>
</StackPanel>
</DockPanel>
<dxe:TextEdit ShowBorder="False" Grid.Row="1" Name="txtComment" Width="Auto" Foreground="Red"
TextWrapping="WrapWithOverflow" EditValue="{Binding Note}" IsEnabled="{Binding IsCommentTextEnable}">
</dxe:TextEdit>
<dxe:TextEdit Text=".............." Grid.Row="2" ShowBorder="False" IsEnabled="False">
</dxe:TextEdit>
</Grid>
</DataTemplate>
and here is the collection + my commands which i want to bind to buttons ,
public ICommand CancelCommand
{
get { return _cancelCommand ?? (_cancelCommand = new CommandHandler(Cancel)); }
set { _cancelCommand = value; }
}
public TList<ProgramNote> NotesCollection
{
get { return _notes; }
set
{
_notes = value;
RaisePropertyChanged("NotesCollection");
}
}
I know i can use this code to bind my commands with button
<Button Command={Binding CancelCommand}
but this command is not present in the collection , i am new in MVVM , kindly help , may be i am missing some little thing to bind my commands , but i am confused that how to add commands in my collection , so that i can get them in my view
You can bind the commands to your data template buttons etc by finding the appropriate viewmodel
example
<DataTemplate x:Key="listItemTemplate">
<Button Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=LixtBox}}"
CommandParameter="{Binding}">
</DataTemplate>
in example we'll find the datacontext of LixtBox which I assume to be your viewmodel then will bind to the command and pass the current object as the command parameter to perform actions on.
you'll then receive the item as parameter in the implementation of your command
public void Execute(object parameter)
{
ProgramNote note = parameter as ProgramNote;
//your logic here, eg cancelling download etc.
}
Thanx to all of you specially thanx to #Sheridan and #PushPraj, I am able to do it now , here is the code of data template in which i have a button
<Button Name="btnCancel" Content="Cancel" Height="20" Width="Auto" DockPanel.Dock="Right"
Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dxe:ListBoxEdit}}"
CommandParameter="{Binding}" Margin="4"></Button>
and this is the code of ListBox
<dxe:ListBoxEdit Name="listComments" Grid.Row="1" ItemTemplate="{StaticResource listItemTemplate}"
ItemsSource="{Binding NotesCollection}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" >
</dxe:ListBoxEdit>
and lastly this is my back end code
listComments.DataContext = viewModel;
It's always difficult to answer new user's questions because they always leave out important information from their questions. However, judging by your question text, it sounds to me like you have set your collection property as the DataContext of your Window. If you want to data bind to your commands instead, then you'll need to change the DataContext to the object that contains both the collection and the commands... an instance of your view model:
DataContext = new YouViewModel();
Now that the DataContext is set to an instance of your view model, you can data bind to its properties as you showed us:
<Button Command="{Binding CancelCommand}" />
...
<ListBox ItemsSource="{Binding NotesCollection}" />
Ahhh, sorry I misunderstood - so your Button is inside the ListBox. In that case, you could try something like this:
<Button Command="{Binding DataContext.CancelCommand,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
This should reach out of the scope of the collection, looking in the DataContext of a Window, so if you have set the instance of your view model to the Window.DataContext, this should work.

Make TabItem select first nested button when clicked (WPF MVVM)

As the title says, I would like the first nested Button to be selected (this button selects a view) when the tab item is clicked. Here is my code below:
<TabItem Header="Scheduling">
<StackPanel Style="{StaticResource ResourceKey=TabStackPanelStyle}">
<RadioButton Command="{Binding BookResourceCommand}" Style="{StaticResource ResourceKey=TabButtonStyle}">Book</RadioButton>
<RadioButton Command="{Binding NewResourceCommand}" Style="{StaticResource ResourceKey=TabButtonStyle}">New</RadioButton>
<RadioButton Command="{Binding EditResourceCommand}" Style="{StaticResource ResourceKey=TabButtonStyle}">Edit</RadioButton>
<RadioButton Command="{Binding DeleteResourceCommand}" Style="{StaticResource ResourceKey=TabButtonStyle}">Delete</RadioButton>
</StackPanel>
</TabItem>
This TabItem sits in a TabControl with a few more similar TabItems. All I want to do is have the TabItem select the first RadioButton (by default) when it is clicked. These radio buttons change a user control in my ViewModel.
I know it would be possible using EventTriggers associated with the TabItem but there must be a better way.
Thanks!
I think in this situation you can use Binding:
TabItem
<TabItem x:Name="MyTabItem" Header="Two">
<Label Content="Some Content" />
</TabItem>
RadioButton
<RadioButton Name="MyButton" Content="Two" IsChecked="{Binding ElementName=MyTabItem, Path=IsSelected}" />
If you want to be when you click on the RadioButton, the tab is not selected, use Mode=OneWay:
<RadioButton Name="MyButton" IsChecked="{Binding ElementName=MyTabItem, Path=IsSelected, Mode=OneWay}" />

WPF UserControl - Binding parent window as command parameter to ContextMenu MenuItem

I have a UserControl with Button inside which opens a ContextMenu when left clicked. I'm trying to pass UserControl's parent Window as a parameter to ContextMenu item's command to close that window, but with no avail. I've tried everything with RelativeSource and PlacementTarget, but parameter is always null. I'm aware that ContextMenu is not part of parent window's VisualTree. I'm currently stuck with this approach, but it is not working.
<Grid x:Name="LayoutRoot">
<Button
HorizontalAlignment="Left"
Margin="0"
Style="{DynamicResource ButtonStyle1}"
VerticalAlignment="Top"
Width="120"
Height="25"
Content="Dashboard Menu"
TextElement.FontWeight="Bold"
Foreground="AliceBlue"
>
<!--Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={ x:Type Window}}}"-->
<Button.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}" >
<MenuItem Header="Open Log Viewer" Command="{StaticResource openLogViewer}" />
<Separator />
<MenuItem Header="Exit" Command="{StaticResource exit}" CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=Window}}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</Grid>
Command is a Referenced command defined in UserControl.Resources:
<my:CommandReference x:Key="exit" Command="{Binding Exit}" />
and it's Execute part is triggered but parameter is always null. So, my question is, what is the right way to bind parent window as CommandParameter of MenuItem. Any help is appreciated, because this thing is bothering me for almost two days.
Right way here is to not pass parent Window to the VM as CommandParameter. If this is MVVM you should be using a Messenger(MVVM Light) / EventAggregator(Prism) approach to send a Message to the Window's code-behind when the command is triggered to Close it.
Referencing Window in the VM is just plain wrong.
Just for reference, what your trying to do "can be done"
something like:
<Grid x:Name="LayoutRoot">
<Button HorizontalAlignment="Left"
Margin="0"
Style="{DynamicResource ButtonStyle1}"
VerticalAlignment="Top"
Width="120"
Height="25"
Content="Dashboard Menu"
TextElement.FontWeight="Bold"
Foreground="AliceBlue"
Tag="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Open Log Viewer" Command="{StaticResource openLogViewer}" />
<Separator />
<MenuItem Command="{StaticResource exit}"
CommandParameter="{Binding PlacementTarget.Tag,
RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
Header="Exit" />
...
Update:
Download Link
When executing the "Exit" command from the ContextMenu you should see Sender Object: MvvmLight16.MainWindow in your Output Window. This output is sent from the VM.

Resources