Passing a string parameter to a textblock - c#

I am trying to pass a string parameter from another xaml page (upon click of a button) into a content dialog and display it inside a textblock in another colour.
Example of the textblock text:
Hey -parameter in red colour-, well -parameter in blue colour-, ... some text... -parameter in another colour-
My current method is to create several textblocks with different properties and then programmatically set the text to the corresponding textblock in the constructor.
There are too much redundant code and I believe there is a more elegant solution to this and I hope that someone could point me in the correct direction. Something tells me its binding but I am not sure how to proceed. (I'm new to XAML and trying to figure my way out by starting on something simple)

You can have an object set as the ContentDialog.DataContext and then use binding to achieve what you want.
In your Button.Click handler, set the data context:
private void Button_Click(object sender, RoutedEventArgs args)
{
ContentDialog dialog = new ContentDialog
{
DataContext = new
{
RedText = "Red Colour",
BlueText = "Blue Colour"
}
};
dialog.ShowAsync();
}
Then in the XAML of the ContentDialog, you can have something as:
<ContentDialog>
<TextBlock>Hey <TextBlock Background="Red" Text="{Binding RedText}"/>, well <TextBlock Background="Blue" Text="{Binding BlueText}"/></TextBlock>
</ContentDialog>

Related

C# Snackbar as Dialog

I want to use the Snackbar from any thread. I declared my Snackbar as i should her;
https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Snackbar
The Wiki says that I can only access the Snackbar from a Dispatcher thread, but how do I implement this?
the user control xaml;
<materialDesign:DialogHost SnackbarMessageQueue="{Binding ElementName=MySnackbar, Path=MessageQueue}" Identifier="DialogSnackbar">
<Grid>
<!-- app content here -->
<materialDesign:Snackbar x:Name="MySnackbar" MessageQueue="{materialDesign:MessageQueue}" />
</Grid>
</materialDesign:DialogHost>
to show a dialog, but i also want to hand over a message;
implementation from https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Dialogs
public static async void ShowDialog()
{
var result = await DialogHost.Show("test", "DialogSnackbar", ExtendedOpenedEventHandler, ExtendedClosingEventHandler);
}
private static void ExtendedOpenedEventHandler(object sender, DialogOpenedEventArgs eventargs)
{
}
private static void ExtendedClosingEventHandler(object sender, DialogClosingEventArgs eventArgs)
{
}
the current message is displayed really weird
All seems to look right for me.
In your ShowDialog() method you only pass a string "test" as content for your DialogHost and you didn't define a DataTemplate in DialogHost.DialogContentTemplate nor a DataTemplateSelector in DialogHost.DialogContentTemplateSelector. So the default behavior of ContentControl kicks in when there is no ContentTemplate or ContentTemplateSelector defined and you don't pass the XAML elements directly as Content. This results in a TextBlock element being created for the dialog content where your string is bound to its Text property. This is exactly what your picture shows.
So to get a different result than what your picture shows you need to either pass directly your XAML elements which you want to show in your dialog (with a root container element and all buttons your dialog needs) or define a DataTemplate or DataTemplateSelector for your DialogHost in your XAML, if you want to use it in a MVVM scenario.
Look at this example from the repo if you need a hint how you can implement this.
You can use:
App.Current.Dispatcher.Invoke(()=>{
//Add the control related code stuff here
});
with the help of #Anateus i get to this solution;
in my MainWindow.xaml i declared this;
<materialDesign:DialogHost VerticalAlignment="Bottom"
HorizontalAlignment="Center"
Identifier="DialogSnackbar">
</materialDesign:DialogHost>
The DialogSnackbarView.xaml - the content of the dialog;
<UserControl ...>
<Grid>
<materialDesign:Snackbar x:Name="MySnackbar"
MessageQueue="{materialDesign:MessageQueue}" />
</Grid>
</UserControl>
to show the Dialog everywhere;
var view = new DialogSnackbarView();
view.MySnackbar.MessageQueue.Enqueue("test");
await DialogHost.Show(view, "DialogSnackbar");

Show text when you press a button

I would like to know a way to make some text appear when you press a button.
I've already created a button and a text box:
<Button Height="25" Width="200" Click="Button_Click" Content="Press this button"/>
<TextBlock Height="50" Width="300" Margin="243,147,249,222" TextAlignment="Center" FontSize="30"/>
Also, I've created a boolean for when you press the button, I donĀ“t know if this is necessary or not.
private void Button_Click(object sender, RoutedEventArgs e)
{
Boolean button = true;
}
Basically, like MaxB said, every control in WPF has a "Visibility" property, that you can change between Visible, Collapsed or Hidden.
Since you already have a Handle for the Button_Click event, all you need to do now is give a name to your TextBlock with the x:Name property like-so :
<TextBlock x:Name="MyTextBlock"/>
Then, in the code of your handler, you can choose which Visibility to apply to the TextBlock according to the state of your boolean.
You can access the TextBlock properties by the name you gave it in the XAML file, like-so :
this.MyTextBlock.Visibility = Visibility.Hidden, for example.
You didn't create a textbox you created a textblock. Firstly create a textbox and give it a name. Then on your Button_click method you can write NameOfTextBox.Text = "Your text";

Working with elements inside a control that is bound to a collection

I have an ObservableCollection<string> that is bound to an ItemsControl whose template is just a Button. The content of this button are 2 TextBlock. I'm trying to use the PreviewMouseRightButtonUp event of the button to toggle the visibility of one of the textblocks, but without being able to use xaml names for elements in the template I'm hitting a wall. Is there a way of getting to the button's content elements via sender in that preview event, or some other way of doing this? This is related to a previous question I had that didn't quite get a usable answer (probably due to my explanation, hence this simplified example). It seems to me that what should happen is I should make a control based off button that adds a property for this toggle, but that is basically what I thought I had in the previous question that wasn't working. I feel like a property and trigger is what most would say is the right way to go?
xaml:
<ItemsControl x:Name="iC" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button PreviewMouseRightButtonUp="Button_PreviewMouseRightButtonUp">
<DockPanel>
<TextBlock Text="normal" DockPanel.Dock="Top"/>
<TextBlock Text="{Binding}" DockPanel.Dock="Top" Visibility="Collapsed"/>
</DockPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
code behind:
ObservableCollection<string> x = new ObservableCollection<string>();
public MainWindow()
{
x.Add("1");
x.Add("2");
InitializeComponent();
iC.ItemsSource = x;
}
If you name the hidden text block "secondTextBlock", then this should work:
private void Button_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
DockPanel dockPanel = (DockPanel)((Button)sender).Content;
TextBlock text = (TextBlock)LogicalTreeHelper.FindLogicalNode(dockPanel, "secondTextBlock");
if (text != null)
{
text.Visibility = Visibility.Visible;
}
}
Regarding your comment below: yes, multiple instances of "secondTextBlock" will be created. See the Snoop screenshot below. But these multiple instances are OK; they do not have any negative impact.

Alternate ways to display forms inside a Grid row in WPF

The WPF application I've created contains a Grid with 3 rows. I have a set of buttons in the 3rd row. On Clicking the Buttons, the forms are displayed in the 2nd row of the Grid. However What I've done is quite messy because I've created all the form contents in the same window and have set the visibility to Hidden.
sample code:
<Grid Name="panel1" Grid.Row="1" Visibility="Hidden">
//contains a lot of textblocks,buttons and images
</Grid>
<Grid Name="panel2" Grid.Row="1" Visibility="Hidden">
//contains a lot of textblocks,buttons and images
</Grid>
<Grid Name="panel3" Grid.Row="1" Visibility="Hidden">
//contains a lot of textblocks,buttons and images
</Grid>
My xaml Code looks like this:
private void Image_MouseLeftButtonDown_1(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
panel1.Visibility = System.Windows.Visibility.Hidden;
panel2.Visibility = System.Windows.Visibility.Visible;
panel3.Visibility = System.Windows.Visibility.Hidden;
}
This approach looks really messy as I've included all the code in the Main Xaml file.
Need some alternate ways to do this. Kindly help.
Create a method like this
private void VisibilityManager(Grid grd)
{
new List<Grid>(){ panel1, panel2, panel3}
.ForEach(x => x.Visibility = Visibility.Hidden);
grd.Visibility = Visibility.Visible;
}
and call it like this
VisibilityManager(panel1);
for making panel1 visible and all other hidden.
In future if you have to increase your grids just make changes inside this method.
You could style a tabcontrol and switch the tab, you could use a contentcontrol and create a binding to the content you want to show. You could also use a databinding (depends on what you want to display) and use a template selector... there are many ways to solve that problem. Just tell a bit more what your contents look like

How click a TextBlock in DataTemplate?

This is my XAML code:
<ListBox ItemsSource="{Binding}" Name="listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="370">
<TextBlock Text="{Binding AuthorName}" x:Name="author" MouseEventLeftDown="click"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the Click Handler
private void click(object sender, RoutedEventArgs e)
{
if(author.Text.Equals("Hi"))
{
// Do Something Special
}
}
The error is:
Error: The name 'author' does not exist in the current context
But I don't understand what is causing this error or why it is occurring.
Your TextBlock with the Name author doesn't exist in the scope of your click handler because it's in a DataTemplate. What's happening is that the author TextBlock is created once for every one of your data items (Presumably an Author class or a Book class of some kind), so you literally can have dozens of controls named author.
You are better off casting your sender in your click handler to a text box and then checking its text property. Something like this:
private void click(object sender, RoutedEventArgs args)
{
var textBox = sender as TextBox;
if(textBox == null)
return;
if(textBox.Text.Equals("hi"))
{
// Do Something Crazy!
}
}
It's probably better to use a UI element designed for touch, such as a HyperlinkButton or a Button. You can style these any way you would like to - especially if you use Expression Blend - but it is good design to include some visual feedback about the Touch.
Also - I'm not sure about your == code - you're comparing the sender (a UI element) against some string expression?
First off, your TextBlock is defined in a DataTemplate; try x:Name instead of Name on your TextBlock.
Secondly it might be quite tricky to click your TextBlock since you will have to press an exact pixel in your TextBlock. To make it easier to click your TextBlock you might want to put a Background on your TextBlock, so it will be a lot easier to click. You can even make the background transparent:
Background="Transparent"
use the gesture listener for create an event handler like "tap" or double" or whatever.
Use this...
private void click(object sender, RoutedEventArgs e)
{
var author = (TextBlock)sender;
if (author.Text.Equals("Hi"))
{
// Do Something Special
}
}

Categories