firstly thanks in advance for any help.
I have an application that i want to add a Navigation menu into. I have created a DataTemplate that has all my buttons and styling and I currently have that in my stylesheet.
<DataTemplate x:Key="Navigation">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<UniformGrid Grid.Row="0" Columns="1">
<Button Visibility="{Binding ElementName=Menu, Path=IsChecked, Converter={StaticResource VisibilityConverter}}" Style="{StaticResource MenuButtonStyle}" >Page 1</Button>
<Button Visibility="{Binding ElementName=Menu, Path=IsChecked, Converter={StaticResource VisibilityConverter}}" Style="{StaticResource MenuButtonStyle}" >Page 2</Button>
<Button Visibility="{Binding ElementName=Menu, Path=IsChecked, Converter={StaticResource VisibilityConverter}}" Style="{StaticResource MenuButtonStyle}" >Page 3</Button>
<Button Visibility="{Binding ElementName=Menu, Path=IsChecked, Converter={StaticResource VisibilityConverter}}" Style="{StaticResource MenuButtonStyle}" >Page 4</Button>
</UniformGrid>
<ToggleButton Grid.Row="1" Style="{StaticResource ToggleBtnToolStyle}" x:Name="Menu" IsChecked="true" Background="Transparent" BorderThickness="0" >
<StackPanel Orientation="Horizontal">
<ContentPresenter Margin="5" Height="50" Content="{StaticResource MenuIcon}"></ContentPresenter>
<Viewbox>
<TextBlock Margin="5" Style="{StaticResource TxtToolStyle}">Menu</TextBlock>
</Viewbox>
</StackPanel>
</ToggleButton>
</Grid>
</DataTemplate>
Currently the only way i have been able to get this working is to remove it from the DataTemplate and implement the grid on each page.
Is there a way of binding to my NavigationViewModel from my DataTemplate that is stored in my Stylesheet?
I'm sorry if this question is badly worded, I'm new to WPF and can do the basic data binding but I'm lost here.
Thanks
Edit
The ViewModel with the Commands i would like to link to looks like this
public abstract class NavigationViewModelBase : ViewModelBase
{
private List<DicomMetadataModel> _dicomMetadata;
//Navigation Cmd
public ICommand AcquisitionPageCmd { get; private set; }
public ICommand ManualEntryWindowCmd { get; private set; }
public ICommand SessionWindowCmd { get; private set; }
public ICommand SettingsWindowCmd { get; private set; }
public ICommand StudyInfoPageCommandCmd { get; private set; }
public ICommand ViewerPageCmd { get; private set; }
public ICommand WorklistPageCmd { get; private set; }
protected NavigationViewModelBase()
{
AcquisitionPageCmd = new RelayCommand(() => Messenger.Default.Send(new GoToPageMessage(Pages.AcquisitionScreen)));
ManualEntryWindowCmd = new RelayCommand(() => Messenger.Default.Send(new ShowDialogMessage(Pages.ManualEntry, DicomMetadata)));
SessionWindowCmd = new RelayCommand(() => Messenger.Default.Send(new ShowDialogMessage(Pages.Session)));
SettingsWindowCmd = new RelayCommand(() => Messenger.Default.Send(new ShowDialogMessage(Pages.Settings)));
ViewerPageCmd = new RelayCommand(() => Messenger.Default.Send(new GoToPageMessage(Pages.Viewer)));
WorklistPageCmd = new RelayCommand(() => Messenger.Default.Send(new GoToPageMessage(Pages.Worklist)));
}
}
}
And them in every page i would like to add the Navigation Menu into the code will look like this
<ContentControl Grid.Column="2" Grid.Row="2" Content="{Binding}" ContentTemplate="{StaticResource Navigation }" />
Related
I am new to XAML forms with MVVM structure.
I have a form designed like the below screenshot. I have a main form and which has 3 buttons.OnClick of each button on the Leftside in the screenshot, it will open a respective user control.
What I am looking for is Automatically Move to Next user control(ImportFile/Summary) on completion of first action (File upload Completed )
Forms screenshot
My Code Looks like below :
MainControl.XAML
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Border CornerRadius="6" Background="SkyBlue" Margin="4">
<WrapPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="2">
<Button x:Name="btnUpload" Background="Transparent" HorizontalAlignment="Left" Command="{Binding Path=UpdateViewCommand}" CommandParameter="FileUpload" KeyboardNavigation.IsTabStop="False" Margin="2">
<StackPanel Orientation="Horizontal">
<Image Source="pack://application:,,,/Resources/NCS.ico" Width="16" Height="16"/>
<Label Content="File Upload View" HorizontalContentAlignment="Center" />
</StackPanel>
</Button>
<Button x:Name="btnImport" Background="Transparent" HorizontalAlignment="Left" Command="{Binding Path=UpdateViewCommand}" CommandParameter="ImportFile" KeyboardNavigation.IsTabStop="False" Margin="2">
<StackPanel Orientation="Horizontal">
<Image Source="pack://application:,,,/Resources/NCS.ico" Width="16" Height="16"/>
<Label Content="Import File" HorizontalContentAlignment="Center" />
</StackPanel>
</Button>
<Button x:Name="btnSummary" Background="Transparent" HorizontalAlignment="Left" Command="{Binding Path=UpdateViewCommand}" CommandParameter="Summary" KeyboardNavigation.IsTabStop="False" Margin="2">
<StackPanel Orientation="Horizontal">
<Image Source="pack://application:,,,/Resources/NCS.ico" Width="16" Height="16"/>
<Label Content="Summary Info" HorizontalContentAlignment="Center" />
</StackPanel>
</Button>
</WrapPanel>
</Border>
<GridSplitter Grid.Column="1"/>
<Local:FileUploadView Height="733" Margin="0.333,0,0,0.333" Grid.Column="2" Width="663"/>
<!--<ContentPresenter Grid.Column="2" Content="{Binding Path=CurrentControl}"/>-->
<ContentControl x:Name="placeHolder" HorizontalAlignment="Center" VerticalAlignment="Center" Height="733" Margin="0.333,0,0,0.333" Grid.Column="2" Width="663" Content="{Binding SelectedViewModel}"/>
</Grid>
MainControl.xaml.cs
public partial class MainControl : UserControl
{
public MainControl()
{
InitializeComponent();
DataContext = new MainControlVM();
}
}
MainControlVM.cs
public sealed class MainControlVM : ViewModelBase
{
private BaseViewModel _selectedViewModel;
public BaseViewModel SelectedViewModel
{
get { return _selectedViewModel; }
set
{
_selectedViewModel = value;
//OnPropertyChanged(nameof(SelectedViewModel));
RaisePropertyChanged(() => SelectedViewModel);
}
}
public ICommand UpdateViewCommand { get; set; }
public override string DisplayName
{
get { return "Main Window"; }
}
public MainControlVM()
{
UpdateViewCommand = new UpdateViewCommand(this);
RegisterOnChangeHandler(() => IsBusy, v => StatusText = v ? "Running..." : "Ready");
}
}
UpdateViewCommand.cs Based On the Parameter on Execute Method it will call respective User control
public class UpdateViewCommand : ICommand
{
private MainControlVM viewModel;
public UpdateViewCommand(MainControlVM viewModel)
{
this.viewModel = viewModel;
}
public void Execute(object parameter)
{
if (parameter.ToString() == "FileUpload")
{
viewModel.SelectedViewModel = new FileUploadViewModel(this.viewModel);
}
else if (parameter.ToString() == "ImportFile")
{
viewModel.SelectedViewModel = new ImportFileViewModel();
}
else if (parameter.ToString() == "Summary")
{
viewModel.SelectedViewModel = new TotalSummaryViewModel();
}
}
}
So i have a view with an ItemsControl which is bound to some ObservableCollection. In the DataTemplate i need two buttons. When i try to bind these buttons to where i have defined them, and i start the application, nothing happens on button click.
The view:
<UserControl x:Class="GraphicalUserInterface.Views._2_ToDoList.ToDoListMainView"
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:GraphicalUserInterface.Views._2_ToDoList"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600"
DataContext="{Binding Source={StaticResource Locator}, Path=ToDoListMain}">
<Grid>
<ItemsControl Margin="5" ItemsSource="{Binding ListEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border CornerRadius="5" BorderThickness="2" BorderBrush="Black" Height="50" Margin="5">
<StackPanel Orientation="Horizontal" Margin="0,5">
<Label FontWeight="Bold">Customer:</Label>
<Label Content="{Binding Customer}" Margin="0,0,20,0"/>
<Label FontWeight="Bold">Trainer:</Label>
<Label Content="{Binding Trainer}" Margin="0,0,20,0"/>
<Label FontWeight="Bold">Date:</Label>
<Label Content="{Binding Date}" Margin="0,0,20,0"/>
<Label FontWeight="Bold">RequestType:</Label>
<Label Content="{Binding RequestType}" Margin="0,0,20,0"/>
<Button Margin="5" Width="100" CommandParameter="{Binding}" Command="{Binding Path=DataContext.ContactBtnClickCommand, RelativeSource= {RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}}">Contact</Button>
<Button Margin="5" Width="100" CommandParameter="{Binding}" Command="{Binding DataContext.AcceptBtnClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}">Accept</Button>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
The class:
public class ToDoListMainVM : ViewModelBase
{
private ObservableCollection<ToDoVM> listEntries;
public ObservableCollection<ToDoVM> ListEntries
{
get { return listEntries; }
set
{
listEntries = value;
RaisePropertyChanged();
}
}
SelectHandler selectHandler = new SelectHandler();
InsertHandler insertHandler = new InsertHandler();
DeleteHandler deleteHandler = new DeleteHandler();
NavigationService navService = new NavigationService();
public RelayCommand<ToDoVM> AcceptBtnClickCommand;
public RelayCommand<ToDoVM> ContactBtnClickCommand;
public ToDoListMainVM()
{
UpdateToDoList();
AcceptBtnClickCommand = new RelayCommand<ToDoVM>((p) =>
{
//Enter into database
insertHandler.InsertAppointmentToDatabase(new AppointmentVM()
{
Customer = p.Customer,
Date = p.Date,
Trainer = p.Trainer
});
//Make it instantly visible in the Calender
Messenger.Default.Send<NewAppointmentMessage>(new NewAppointmentMessage(p.Customer, p.Date));
//Delete from ToDo (View)
ListEntries.Remove(p);
//Delete from Db
deleteHandler.DeleteToDo(p);
//Set view to Calender
navService.NavigateTo("MyTrainingsMain");
});
View Model:
public class ToDoVM
{
public int ToDoVMID { get; set; }
public string RequestType { get; set; }
public DateTime Date { get; set; }
public CustomerVM Customer { get; set; }
public TrainerVM Trainer { get; set; }
}
The command properties need to be properties, with a getter. You can't bind to a field.
public RelayCommand<ToDoVM> AcceptBtnClickCommand { get; private set; }
public RelayCommand<ToDoVM> ContactBtnClickCommand { get; private set; }
The rest of your code is fine. The bindings are correct. You could simplify them slightly, but they work perfectly just the way you wrote them.
Command="{Binding DataContext.ContactBtnClickCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
I have a gridview in UWP app and I have put a button in each gridview item in datatemplate so that it can be used to delete/remove that specific item from the gridview ( removing it from observableCollection behind). I am not using MVVM approach, because I am not much familiar with it, I am using a normal Observable Collection for binding of data and data template.
if you can suggest me a better way to do it, myabe using MVVM please suggest me how to do it. Thanks in advance
Code :
XAML GRID VIEW (button with the red back ground is the button I wanna use to delete item)
<controls:AdaptiveGridView Name="HistoryGridView" StretchContentForSingleRow="False"
Style="{StaticResource MainGridView}"
ItemClick ="HistoryGridView_SelectionChanged"
ItemsSource="{x:Bind HistoryVideos, Mode=OneWay}">
<controls:AdaptiveGridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<StackPanel Margin="4" >
<Grid>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Style="{StaticResource TransparentButton}" Width="36">
<fa:FontAwesome Icon="Close" FontSize="20" HorizontalAlignment="Center" Foreground="White"
/>
</Button>
<Image Canvas.ZIndex="0" Source="{x:Bind Thumbnail}" Style="{StaticResource GridViewImage}"/>
<Border Style="{StaticResource TimeBorder}" Height="Auto" VerticalAlignment="Bottom"
Canvas.ZIndex="1"
HorizontalAlignment="Left">
<TextBlock Text="{x:Bind Duration}" Foreground="White" Height="Auto"/>
</Border>
</Grid>
<TextBlock Text="{x:Bind Name}" Style="{StaticResource GridViewVideoName}"/>
<TextBlock Text="{x:Bind ParentName}" Style="{StaticResource GridViewParentName}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock Text="{x:Bind Views}" Style="{StaticResource GridViewViews}"/>
<TextBlock Text="Views" HorizontalAlignment="Right"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>
Code Behind
public History()
{
this.InitializeComponent();
HistoryVideos = new ObservableCollection<Video>();
}
public ObservableCollection<Video> HistoryVideos { get; private set; }
I am using onnavigated to method for filling the collection and it works fine and also I guess that is not relevent here.
We can add the Command to the Button to invoke when this button is pressed and we can use parameter to pass to the Command property.
To use the Command, we should be able to define a DelegateCommand class that inherits from the ICommand.
For example:
internal class DelegateCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public DelegateCommand(Action<object> execute)
{
this.execute = execute;
this.canExecute = (x) => { return true; };
}
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
public void Execute(object parameter)
{
execute(parameter);
}
}
We can add the Id property in the Video, then we can pass the Id property to the CommandParameter. When we click the Button, the ExecuteDeleteCommand method will be fired. We can use the Id to find the Video in the HistoryVideos and use the Remove method to remove it.
The ViewModel code:
internal class ViewModel
{
private ObservableCollection<Viedo> _videos;
public ObservableCollection<Viedo> Videos
{
get
{
return _videos;
}
set
{
if (_videos != value)
{
_videos = value;
}
}
}
public ICommand DeleteCommand { set; get; }
private void ExecuteDeleteCommand(object param)
{
int id = (Int32)param;
Viedo cus = GetCustomerById(id);
if (cus != null)
{
Videos.Remove(cus);
}
}
private Viedo GetCustomerById(int id)
{
try
{
return Videos.First(x => x.Id == id);
}
catch
{
return null;
}
}
public ViewModel()
{
Videos = new ObservableCollection<Viedo>();
for (int i = 0; i < 5; i++)
{
Videos.Add(new Viedo());
Videos[i].Name = "Name";
Videos[i].Id = i;
}
this.DeleteCommand = new DelegateCommand(ExecuteDeleteCommand);
}
}
The XAML code:
<GridView Name="MyGridView" ItemsSource="{Binding Videos}">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"></TextBlock>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Width="36" Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
</Button>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The code behind:
private ViewModel myViewModel;
public MainPage()
{
this.InitializeComponent();
myViewModel = new ViewModel();
MyGridView.DataContext = myViewModel;
}
Update:
<GridView Name="MyGridView" ItemsSource="{x:Bind myViewModel.Videos}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:Viedo">
<StackPanel>
<TextBlock Text="{x:Bind Name}"></TextBlock>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Width="36" Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
</Button>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
I have a ListView with a DataTemplate, inside this templates there are several textblocks and a button. The button has a contextmenu with fixed items. The binding of the listviewitems works fine, but binding a property to the contextmenu does not seem to work.
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Grid.Column="0" Grid.RowSpan="2" Background="{Binding StateColor}">
</Grid>
<TextBlock Grid.Column="1" Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Anrufen" Name="mn_call" Click="mn_call_Click" DataContext={Binding Number} />
</ContextMenu>
</Button.ContextMenu> ...</Button>
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstEntry.KDKGRS}" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="{Binding FirstEntry.ConvertedKGFARBE}" />
<TextBlock Text="{Binding FirstEntry.ADNAMI}" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have removed some unnecessary bits of the code (style and columndefinitions) for readability.
The important part is the MenuItem inside the Button. My underlying class has a public string property Number. This should be passed to the menu item. But the DataContext of the MenuItem is always null inside the click event.
I've read something about the contextmenu not beeing part of the visual tree, but I can't wrap my head around it. Could somebody explain the issue with the binding?
Edit Code for the underlying class:
Again removed some unnecessary code for the question
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
And the binding of the ListBox:
List<PhoneClient> clients = new List<PhoneClient>();
clients = load(); //returns active Clients
lv_clients.ItemsSource = clients;
Bridging the gap
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Anrufen" Click="mn_call_Click" Name="mn_call"
DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
Handler
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
// Do Stuff
}
EDIT
MainWindow.xaml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="10">
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="LightGray" Width="100">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Background="LightGreen">
</Grid>
<TextBlock Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Show" Click="mn_call_Click" Name="mn_call" DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
</Button.ContextMenu> ...
</Button>
<StackPanel Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Foo" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="Blue" />
<TextBlock Text="Bar" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
namespace WpfApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<PhoneClient> clients = new List<PhoneClient>();
clients.Add(new PhoneClient() { Name = "Kumar", Number = "0101010", Extension = "555", State = "New York" });
clients.Add(new PhoneClient() { Name = "Shanaya", Number = "1010101", Extension = "555", State = "New Jersey" });
clients.Add(new PhoneClient() { Name = "Billy Bob", Number = "6543210", Extension = "555", State = "Single" });
lv_clients.ItemsSource = clients;
}
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String State { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
MessageBox.Show("Number " + number);
}
private void Button_ListItem_Click(object sender, RoutedEventArgs e)
{
Button currentButton = (Button)sender;
PhoneClient data = (PhoneClient)currentButton.DataContext;
MessageBox.Show(data.Name + " tapped");
}
}
}
I am trying to build a WPF application (using C#.net) in which I want to add button inside ListBox.
Here is the data template which I have placed in the resource dictionary
<DataTemplate x:Key="MYTemplate">
<StackPanel Margin="4">
<DockPanel>
<TextBlock Text="ISBN No:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue" />
<TextBlock Text=" " />
<TextBlock Text="{Binding ISBN}" Foreground="LimeGreen" FontWeight="Bold" />
</DockPanel>
<DockPanel>
<TextBlock Text="Book Name:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue"/>
<TextBlock Text=" " />
<TextBlock Text="{Binding BookName}" Foreground="LimeGreen" FontWeight="Bold" />
</DockPanel >
<DockPanel >
<TextBlock Text="Publisher Name:" DockPanel.Dock="Left" Margin="5,0,10,0" Foreground="AliceBlue" />
<TextBlock Text=" " />
<TextBlock Text="{Binding PublisherName}" Foreground="LimeGreen" FontWeight="Bold" />
</DockPanel>
<DockPanel>
<Button Name="MyButton" Content="Click Me">
</Button>
</DockPanel>
</StackPanel>
</DataTemplate>
How do add the click event to the button tag in the above template?
Also where should I place the method which will be called when button is clicked.
Nilesh,
you should be using binding the button to a command.
For example if your data item is defined like this:
public class MyItem : ViewModelBase
{
public MyItem()
{
ClickMeCommand = new RelayCommand(ClickMe);
}
private void ClickMe()
{
Debug.WriteLine("I was clicked");
}
public string ISBN { get; set; }
public string BookName { get; set; }
public string PublisherName { get; set; }
public ICommand ClickMeCommand { get; set; }
}
Then this will invoke the ClickMe method.
<DockPanel>
<Button Content="Click Me" Command="{Binding ClickMeCommand}" />
</DockPanel>
Or you can put the command in the parent view model:
public class MainViewModel : ViewModelBase
{
public IEnumerable<MyItem> Items { get; private set; }
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
Items = new List<MyItem>
{
new MyItem{ ISBN = "ISBN", BookName = "Book", PublisherName = "Publisher"}
};
ClickMeCommand = new RelayCommand<MyItem>(ClickMe);
}
private void ClickMe(MyItem item)
{
Debug.WriteLine(string.Format("This book was clicked: {0}", item.BookName));
}
public ICommand ClickMeCommand { get; set; }
}
and bind to that
<DockPanel>
<Button Content="Click Me" CommandParameter="{Binding}" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}, Path=DataContext.ClickMeCommand}" />
</DockPanel>
Note that the code above is using MVVM light and I'm assuming you have
<ListBox ItemTemplate="{StaticResource MyTemplate}" ItemsSource="{Binding Items}"/>