RibbonSplitButton click event - wpf

Gentelman,
I'm binding a collection to RibbonSplitButton (basically, showing 3 values: red, green, blue) Everything works fine except of the problem I have to figure out which color (item) has been chosen:
Here's my code:
<r:RibbonSplitButton Name="TagEm"
LargeImageSource="Images\pencil_32.png"
Label="Tag"
ItemsSource="{Binding Path=TagCollection}"
Click="TagEm_Click">
<r:RibbonSplitButton.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Descr}" />
</DataTemplate>
</r:RibbonSplitButton.ItemTemplate>
</r:RibbonSplitButton>
Code behind:
private void TagEm_Click(object sender, RoutedEventArgs e)
{
}
Something like (Tag)TagEm.Items.CurrentItem;
Could someone give me a hint, please?
Many thanks in advance!
N.

Do not use the RibbonSplitButton Click event. Instead use the TextBox MouseLeftButtonUp event.
XAML:
<r:RibbonSplitButton
Name="TagEm"
LargeImageSource="Images\pencil_32.png"
Label="Tag"
ItemsSource="{Binding Path=TagCollection}">
<r:RibbonSplitButton.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp" />
</DataTemplate>
</r:RibbonSplitButton.ItemTemplate>
</r:RibbonSplitButton>
Event Handler:
private void TextBlock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Tag clickedTag = (sender as TextBlock).DataContext as Tag;
}

Related

WPF TextBox lostFocus event trigger

I am new to WPF,
In my mainWindow I have multiple TextBox, so whenever a user enters different inputs in these textbox I want to implement those changes in the code behind, as soon as user leaves the focus of the textbox.
For example, my textBox looks like this:
<TextBox Name="SpiralAngleTextBox"
Grid.Column="1" Grid.Row="4"
Margin="5,5,5,5" SelectedText="0"/>
I am not looking to do any kind of input validation. What I want is to trigger some calculations or call a function whenever the TextBox leaves focus after contents of TextBox is updated.
You can write an EventHandler
<TextBox Name="SpiralAngleTextBox"
Grid.Column="1" Grid.Row="4"
Margin="5,5,5,5" SelectedText="0" LostFocus="SpiralAngleTextBox_LostFocus"/>
and in the xaml.cs
private void SpiralAngleTextBox_LostFocus(object sender, RoutedEventArgs e)
{
foo();
}
If you just want it to do stuff when the textbox content changes you can try something like this:
<TextBox Name="SpiralAngleTextBox"
Grid.Column="1" Grid.Row="4"
Margin="5,5,5,5" SelectedText="0" LostFocus="SpiralAngleTextBox_LostFocus"
TextChanged="SpiralAngleTextBox_TextChanged"/>
and in the xaml.cs
bool hasChanged;
private void SpiralAngleTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if(hasChanged)
foo();
hasChanged = false;
}
private void SpiralAngleTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
hasChanged = true;
}
All you need to do is to bind to TextBox.Text
<TextBox Text="{Binding MyProperty}" />
Where MyProperty is some property in your code-behind. This is because TextBox.Text updates on lost focus (UpdateSourceTrigger=LostFocus by default.) You can learn more here: https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-control-when-the-textbox-text-updates-the-source

Radio button : difference between user click and programatic selection

I have a group of 2 radio buttons and I need to know when the user clicks on one of them.
One of these 2 radio buttons must be selected by default (at page creation).
Why the check callback is called when I select the radiobutton from code? How can I differentiate them ? It bothers me since when the user perform the action, I must perform a web request, but when I select it from code at init time, it mustn't do any req.
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
Search(ContractTextBox.Text, true);
}
<ItemsControl ItemsSource="{Binding SelectedMainSearchItem.SubLevels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<RadioButton Content="{Binding Name}"
GroupName="ExclusiveGroupL3"
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Checked="RadioButton_Checked"
FontSize="18"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
The usual way to deal with a situation like this is to define a bool property to use as a 'flag':
private bool isUserSelection = true;
...
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
if (isUserSelection) Search(ContractTextBox.Text, true);
}
And when you set the CheckBox value programmatically, set the flag to false:
isUserSelection = false;
SetCheckBoxValue(true);
isUserSelection = true;

TextBlock MouseDown URL - How get my url in my code behind?

I ve a list from sharepoint and i collect from this list an hyperlink.
As i want my textbox to be like an hyperlink I ve added an event on mousedown to open this hyperlink, My concern is how to collect this hyperlink in the codebehind with the sender.
For the moment I've just hide this hyperlink in the tooltip maybe i can manage this differently any suggestion will be grantly appreciated.
My point so far, i don't know how to get this tooltip in the code behind.
Thanks
My XAML Code :
<ListBox Name="ListboxTips" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Picture}" Height="20"></Image>
<TextBlock MouseDown="TextBlock_MouseDown_URL" TextDecorations="Underline"
Margin="10,10,20,10" Width="160" TextWrapping="Wrap"
Text="{Binding Path=TitleTip}"
ToolTip="{Binding Path=URL}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My code behind :
foreach (SPSClient.ListItem item in TipsList)
{
var tips = new Tips();
tips.TitleTip = item.FieldValues.Values.ElementAt(1).ToString();
tips.App = item.FieldValues.Values.ElementAt(4).ToString();
// get the Hyperlink field URL value
tips.URL = ((FieldUrlValue)(item["LinkDoc"])).Url.ToString();
//should collect the description of the url
//tips.URLdesc = ((FieldUrlValue)(item["LinkDoc"])).Description.ToString();
tips.Picture = item.FieldValues.Values.ElementAt(4).ToString();
colTips.Add(tips);
}
ListboxTips.DataContext = colTips;
....
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//string test = (ToolTip)(sender as Control).ToString();
System.Diagnostics.Process.Start("http://www.link.com");
//System.Diagnostics.Process.Start(test);
}
Thanks a lot,
You can just access the property directly. It is not elegant, but will work!
private void TextBlock_MouseDown_URL(object sender, MouseButtonEventArgs e)
{
TextBlock txtBlock = sender as TexBlock;
// just access the property
string url = txtBlock.ToolTip as string;
}
A more elegant approach might be to use a Button, Hyperlink or something that exposes a Command, so that you can bind the 'click' action to a command on your view model that performs the action you wish to execute.
usually you stick any data you want to trespass somewhere to Tag attribute.
<TextBlock .. Tag="{Binding Path=URL}" />
This is easily retrievable as a public property:
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var tb = sender as TextBlock;
if(tb != null)
{
var neededUrl = tb.Tag;
}
}

How to Identify button for list item

How do i access the object UserNames, that is bound to the list??
What i did so far:
Item of the list is object in my case:
new List<UserNames>();
this.users.Add(new UserNames() {Id = 1, UserName = "name 1"});
I am using data template for which i have label and button.
My List is as follows:
<ListBox Grid.Column="1" Grid.Row="1" Name="listBox1" ItemsSource="{Binding}" SelectedValuePath="Id">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Vertical">
<StackPanel>
<Label Content="{Binding UserName}" />
</StackPanel>
<StackPanel Name="ButtonStackPanel">
<Button Name="MyButton" Content="Click Me" Click="MyButton_Click">
</Button>
</StackPanel>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Where my method for Button is. As you can see i did try to utilise the parent option, but without sucess
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//StackPanel panel = (StackPanel)((Button)sender).Parent;
//WrapPanel wrapPanel = (WrapPanel) panel.Parent;
//ListItem listItem = (ListItem) wrapPanel.Parent;
//ListBox box = (ListBox) listItem.Parent;
//UserNames itemToReport = (UserNames) (box.SelectedItem);
//MessageBox.Show(itemToReport.UserName);
}
You can use the Button's DataContext, since it will be your UserName object
private void MyButton_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
UserNames data = b.DataContext as UserNames;
MessageBox.Show(data.UserName);
}
I've always thought that with WPF, your application is the DataContext, while the UI objects like Buttons, ListBoxes, TextBoxes, etc are simply a pretty layer that sits on top of the DataContext to allow the User to interact with it.
In the XAML, set the Tag property to the current item.
In the click handler, cast it back.
Usernames user = (sender as Button).Tag as Usernames;
To bind a datacollection it is often easiest to use an ObservableCollection (if the data is changing runtime). When you do the binding you have to define a datacontext, a datasoure and a datapath. I will advice you to read some more about binding on MSDN :D
This will work for you -
MessageBox.Show(((sender as Button).DataContext as UserNames).UserName);

Xaml Binding outside itemtemplate

I would like to bind data of my listbox. Imagine I have something like :
<ListBox ItemsSource="{Binding MyList}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text={Binding Value} />
<TextBlock Text={Binding AbsoluteValue} />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MyList contains an observable collection of an object that has a property named "Value"
AbsoluteValue is a property of the view model, as the MyList property.
Of course, the seconde textbox will have always the same value, but it is what I want :)
How can I tell the binding that the datacontext is not the same for the second textbox ?
Thanks in advance for any help
EDIT : my real sample is a StackPanel.
I've tryed
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = sender as StackPanel;
stackPanel.SetBinding(StackPanel.VisibilityProperty, new Binding("Loaded") { Source = DataContext, Mode = BindingMode.TwoWay });
}
but it's not working
XAML:
<TextBlock x:Name="tbAbsoluteValue" Loaded="AbsoluteValue_Loaded" />
Codebehind:
void AbsoluteValue_Loaded(object sender, RoutedEventArgs e)
{
TextBlock absoluteValue = sender as TextBlock;
absoluteValue.SetBinding(TextBlock.TextProperty, new Binding("AbsoluteValue") { Source = VIEW_MODEL_OBJECT, Mode = BindingMode.TwoWay });
}
That's one way to achieve what you want, you could also use a converter too, or create a StaticResource in your Resources for the VM and bind to that as a source.

Resources