WPF multiple buttons, same click function but different parameter - c#

I want to make several buttons with the same click function but different parameter. Like this
XAML:
<Button Click="MyClickFunction(1)" Content="MyFunc(1)"/>
<Button Click="MyClickFunction(2)" Content="MyFunc(2)"/>
<Button Click="MyClickFunction(3)" Content="MyFunc(3)"/>
<Button Click="MyClickFunction(4)" Content="MyFunc(4)"/>
C#:
private void MyClickFunction(object sender, RoutedEventArgs e, int myParam)
{
//do something with parameter e.g. MessageBox.Show()
MessageBox.Show(myParam.ToString());
}
How to I pass the parameter in xaml tag or I will have to do it other ways?

Use Tag property in the button. Like this:
<Button Click="MyClickFunction" Tag="1" Content="MyFunc(1)"/>
<Button Click="MyClickFunction" Tag="2" Content="MyFunc(2)"/>
<Button Click="MyClickFunction" Tag="3" Content="MyFunc(3)"/>
<Button Click="MyClickFunction" Tag="4" Content="MyFunc(4)"/>
And in the code behind:
private void MyClickFunction(object sender, RoutedEventArgs e)
{
var tag = ((Button)sender).Tag;
MessageBox.Show(tag.ToString());
}

Related

Show a sequence of images in WPF then close form

I have a window that shows an open lock.
When the user clicks a button the lock must change to closed, wait a second and then close the windows.
How can I do that using WPF?
Here is my initial xaml:
<Button Grid.Row="2" BorderThickness="0" Background="Transparent" Margin="32"
IsTabStop="False" Click="BtnUnlockClick">
<Button.Content>
<Grid>
<Image Grid.Row="1" Source="/Common.Wpf;component/images/unlocked.png" Visibility="Visible" Name="imgUnlocked"/>
<Image Grid.Row="1" Source="/Common.Wpf;component/images/locked.png" Visibility="Collapsed" Name="imgLocked"/>
</Grid>
</Button.Content>
</Button>
and C#:
private void BtnUnlockClick(object sender, RoutedEventArgs e)
{
//do stuff here
}
Put only one Image element into the Button's Content.
<Button Click="BtnUnlockClick" ...>
<Image Source="/Common.Wpf;component/images/unlocked.png"/>
</Button>
In the Click event handler change its Source, wait a second, then close the Window. The handler method must be declared async.
private async void BtnUnlockClick(object sender, RoutedEventArgs e)
{
var image = (Image)((Button)sender).Content;
image.Source = new BitmapImage(
new Uri("pack://application:,,,/Common.Wpf;component/images/locked.png"));
await Task.Delay(1000);
Close();
}

Button inside button (WPF + Caliburn.Micro)

In regular WPF you can have a button inside another button, and to prevent both button events being raised when you click the inner button, you can have the following XAML (As per this question):
<Button Click="OuterClick">
<Grid>
<SomeOtherContent />
<Button Click="InnerClick" />
</Grid>
</Button>
And then in the code-behind use the Handled property on the event so that OuterClick is not raised when the inner button has been clicked:
private void OuterClick(object sender, RoutedEventArgs e) {
// Do something
}
private void InnerClick(object sender, RoutedEventArgs e) {
// Do something else
e.Handled = true;
}
However, following the usual Caliburn.Micro conventions you'll have the following XAML:
<Button x:Name="OuterClick">
<Grid>
<SomeOtherContent />
<Button x:Name="InnerClick" />
</Grid>
</Button>
With this in the ViewModel:
private void OuterClick() {
// Do something
}
private void InnerClick() {
// Do something else
}
How can I make sure that not both InnerClick() and OuterClick() are raised when I click the InnerButton?
EDIT: Or, what other kind of controls can I use instead?
<StackPanel cal:Message.Attach="[Event MouseDown]=[Action OuterClick()]">
<StackPanel Orientation="Horizontal">
<SomeotherContent />
<Button x:Name="InnerClick" />
</StackPanel>
</StackPanel>
In Your viewmodel
public void OuterClick()
{
//Do something
}
public void InnerClick()
{
//Do something
}
use stackpanel and apply event for that one.
This will help you.

clicking messagebox.show() hides showdialog() window

I have following code in WPF:
private void BtnTicketPrice_Click(object sender, RoutedEventArgs e)
{
TicketPrice TP = new TicketPrice();
TP.ShowDialog();
}
in New Window form i have following code:
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("sometext");
}
on clicking messagebox button the form (TicketPrice) also is closing;
how to show messagebox without closing the form?
If i'd change TP.ShowDialog(); to TP.Show();, it works correctly. I have this problem only with this TP.ShowDialog();
xaml of button
<Button x:Name="BtnSave" HorizontalAlignment="Left" Margin="619,362,0,0" VerticalAlignment="Top" Width="165" Height="66" IsCancel="True" TabIndex="4" Click="BtnSave_Click">
<StackPanel Orientation="Horizontal">
<TextBlock Text="save " HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="SemiBold" />
<Image Source="pack://siteoforigin:,,,/Resources/Save.png" Height="50" Width="59" />
</StackPanel>
</Button>
You're seeing the IsCancel property on the Button working as advertised. Don't set it to true and clicking the button won't automatically close the dialog.

How to pass an argument over a GoBackCommand in a Windows Store App

I want to pass an argument over to the previous page I visited when using a Binding GoBackCommand in the NavigationHelper.
The Back button in XAML
<Button x:Name="backButton"
Margin="39,59,39,0"
Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
IsEnabled="{Binding IsBackEnabled}"/>
I want to pass the argument similar to when I trigger an EventHandler and navigate forward, e.g
C# Code Behind
Send the argument
private void Button_Click(object sender, RoutedEventArgs e)
{
string myArg = "Hello";
this.Frame.Navigate(typeof(AnotherPage), myArg);
}
And retrieve it
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string myParam = e.Parameter.ToString();
}
Here is a solution although there is probably a better way to do this
C# Code Behind
In your Page with the GoBackCommand, declare a GoBack method:
private void GoBack()
{
string myArg = "Hello";
this.Frame.Navigate(typeof(AnotherPage), myArg);
}
Then in your Page constructor just set the GoBackCommand to your GoBack method:
public MyPage()
{
this.InitializeComponent();
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += navigationHelper_LoadState;
this.navigationHelper.SaveState += navigationHelper_SaveState;
this.navigationHelper.GoBackCommand = new RelayCommand(GoBack);
}
You can use CommandParameter in your XAML to do that.
<Button x:Name="backButton"
Margin="39,59,39,0"
Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
CommandParameter="This is my parameter"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"
IsEnabled="{Binding IsBackEnabled}"/>

Dynamically Adding event handlers to WPF

I'm looking for help with an app I'm building. I've an xml file being read into an app. This XML is of the following structure:
`<Tabs>
<Tab>
<Search name="ListSearch" Title="SearchHeader">
<Label Name="lblSchema"></Label>
<ComboBox Name="comboxSchema" Visibility="Visible" IsEnabled="True" ItemSource="{Binding AvailableSchema}" SelectedValue="{Binding SelectedSchema}" />
<ComboBox Name="comboxList" Visibility="Visible" IsEnabled="True" ItemSource="{Binding AvailableList}" SelectedValue="{Binding SelectedList}" />
<Label Name="lblCriteria"></Label>
<ComboBox Name="comboxFields" Visibility="Visible" IsEnabled="True" ItemSource="{Binding AvailableFields}" SelectedValue="{Binding SelectedField}" />
<ComboBox Name="comboxOperator" Visibility="Visible" IsEnabled="True" ItemSource="{Binding Operations}" SelectedValue="{Binding SelectedOperator}" />
<TextBox Name="txtBoxInputValue" Visibility="Visible" IsEnabled="True" Text="{Binding InputValue}" />
<CustomControl type="DatePicker"></CustomControl>
<Button Name="btnAddQueryLine" Content="{Binding TextOnAddQueryButton}" Command="{Binding CamlAddQueryLine}" Action="Publish"></Button>
<Button Name="btnPasteQueryLine" Content="{Binding TextOnPasteQueryButton}" Command="{Binding CamlPasteQueryLine}" Action="Preview"></Button>
<Button Name="btnRemoveQueryLine" Content="{Binding TextOnRemoveQueryButton}" Command="{Binding CamlRemoveQueryLine}" Action="UnPublish"></Button>
<Button Name="btnClearQuery" Content="{Binding TextOnClearQueryButton}" Command="{Binding CamlClearQuery}" Action="UnPreview"></Button>
<Button Name="btnCamlSearch" Content="{Binding TextOnSearchQueryButton}" Command="{Binding CamlSearch}" Action="Meh"></Button>
<Button Name="btnCloseSearch" Content="{Binding TextOnCloseQueryButton}" Command="{Binding CloseSearch}" Action="NewMeh"></Button>
</Search>
</Tab>
</Tabs>`
So I read in the xml, and use methods like this to add buttons etc to the ribbon:
private void AddButtonToGroup(string header,RibbonGroup group,string command,string action)
{
RibbonButton button = new RibbonButton();
button.Label = header;
button.Name = action;
button.Click += new RoutedEventHandler(button_Click);
group.Items.Add(button);
}
with the following event handler:
void button_Click(object sender, RoutedEventArgs e)
{
Button clicked = (Button)sender;
MessageBox.Show("Button Clicked!");
MessageBox.Show("Performing Action:" + clicked.Name);
}.
The problem I have, is that this isn't the requirement- the event handler is hard coded. Is there any way to create event handlers dynamically? Can anyone point me in the right direction?
You could create a method that returns an Action<object, RoutedEventArgs>:
private Action<object, RoutedEventArgs> MakeButtonClickHandler()
{
return (object sender, RoutedEventArgs e) =>
{
// Put your code here, it will be called when
// the button is clicked
};
}
So MakeButtonClickHandler returns a new anonymous function each time it's called. Then assign it like this:
button.Click += new RoutedEventHandler(MakeButtonClickHandler());
Another way of accomplishing the same thing is to do this inline, like so:
button.Click += (object sender, RoutedEventArgs e) =>
{
// Put your code here
};
For some more information, take a look at Anonymous Functions on MSDN.
You need to define a set of actions that the user will be able to do. Then assign a name to each one of them and implement the actions in code.
For example, the XML would be:
<Button Content="TextOnAddQueryButton" Command="CamlAddQueryLine"></Button>
In code, you would assign the event handler like this:
private void AddButtonToGroup(string header,RibbonGroup group,string command,string action)
{
RibbonButton button = new RibbonButton();
button.Tag = command;
//...
}
And the handler for the button would be:
void button_Click(object sender, RoutedEventArgs e)
{
Button clicked = (Button)sender;
switch (clicked.Tag)
{
case "CamlAddQueryLine":
// Call action for CamlAddQueryLine
break;
}
}

Categories