There are pictures of what I want to achieve in this question.
I tried putting the TextBlock and the Button in a WrapPanel, and this works for single-line text but not for multi-line text.
<WrapPanel>
<TextBlock
TextTrimming="WordEllipsis"
TextWrapping="WrapWithOverflow" .../>
<Button .../>
</WrapPanel>
The picture below shows what's happening. When the TextBlock text becomes 2 lines the second line takes the whole width of the first line, which is logical.
I thought of chopping the string by words and using an ItemsControl with WrapPanel as ItemsPanel. But the text may become longer, and there isn't space for more than 2 lines, that's why I put the TextTrimming="WordEllipsis" there; the remaining text will be trimmed and the button will be at the end of the second line, in that case.
Update: Well it turned out to be not so easy, I went with changing my UI to something simpler like putting a rounded button on the right.
If you don't mind to use TextBox insteaf of TextBlock, it has TextBox.GetRectFromCharacterIndex method to get the rectangle of character by index number and you can utilize it to adjust the position of Button accordingly.
The following is just a proof of concept and there is much room to modify.
Xaml:
<Grid Width="200" Height="100">
<TextBox x:Name="textBox"
TextWrapping="WrapWithOverflow" AcceptsReturn="True"
TextChanged="TextBox_TextChanged"/>
<Button x:Name="button"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="END" Padding="0" VerticalContentAlignment="Center"/>
</Grid>
Code behind:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
AdjustButtonPosition();
}
private void AdjustButtonPosition()
{
if (this.textBox is null || this.button is null)
return;
var index = textBox.Text.Length;
var rect = textBox.GetRectFromCharacterIndex(index);
button.Margin = new Thickness(rect.Right, rect.Top, 0, 0);
button.Height = rect.Height;
}
Related
I am a newbie in WPF trying to create his first normal project which is a notes application.
Every note is linked to a button and I thought it'll look beautiful in StackPanel.
I am dynamically creating buttons within StackPanel, but the problem is that when I scroll down the list of Buttons last Button can't be seen fully. I thought it was because of the Margin and tried to adjust it, but it didn't help, also auto Height and Width didn't help. StackPanel is within ScrollViewer and when I reach the end of ScrollBar I just can see half of last button ?
Here is StackPanel's XAML code:
<ScrollViewer VerticalScrollBarVisibility="Auto"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Grid.RowSpan="3" Margin="50 -50 50 5" >
<StackPanel x:Name="ButtonPanel"/>
</ScrollViewer>
That is how I create Button:
dynamicTextBox.Add(SearchNotes);
dynamicTextBox[index_of_buttons] = new TextBox();
Grid.SetRow(dynamicTextBox[index_of_buttons], 1);
Grid.SetColumn(dynamicTextBox[index_of_buttons], 0);
this.ButtonPanel.Children.Add(dynamicTextBox[index_of_buttons]);
dynamicTextBox[index_of_buttons].IsReadOnly = false;
dynamicTextBox[index_of_buttons].Text = "";
Where dynamicTextBox is List<> of TextBoxes to which is applied Template(I think it is not necessary to see Template to resolve the problem)
This is how it looks like:
Can't see the whole button(the last one)
So I wanna see the whole button.
As Andy wrote in the comment section, ListBox is best solution for this problem.
I tried this one to make it look like exactly same as it was in StackPanel
Xaml:
<ListBox Name="ListBoxOfButtons" Background="#404040" BorderThickness="0"
HorizontalContentAlignment="Stretch" Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="3" Grid.RowSpan="3" Margin="50 -20 50 5">
</ListBox>
C#:
var txtBox = new TextBox();
txtBox.Template = FindResource("TemplateForTextBox") as ControlTemplate;
ListBoxOfButtons.Items.Add(txtBox);
This is how last button looks like now
I am currently developping an interface that shows multiple camera shot and the direct view of the camera.
What i need to do is put a label on a picturebox (picturebox that refresh camera live every frame).
My problem is that when the picturebox refresh, the label get under it.
Here's how my XAML code is made :
<Grid x:Name="GridCam4" Grid.Column="1" Grid.Row="1" Margin="0,0,24,0">
<WindowsFormsHost x:Name="DisplayWindow" Foreground="#FFA0A0A0" Background="#FFA0A0A0" Panel.ZIndex="2" Height="435" Width="678">
<forms:PictureBox x:Name="picturebox1" BackgroundImageLayout="None"/>
</WindowsFormsHost>
<Label x:Name="LabelLive" Content="Live :" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="102" Width="206" FontSize="36" Panel.ZIndex="12" Foreground="White"/>
</Grid>
And there is my C# code :
private void onFrameEvent(object sender, EventArgs e)
{
uEye.Camera Camera = sender as uEye.Camera;
Camera.Memory.GetLast(out s32MemID);
//Display the image on the screen (Refresh the picturebox with last picture taken)
Camera.Display.Render( DisplayHandle, uEye.Defines.DisplayRenderMode.FitToWindow);
Camera.Memory.Unlock(s32MemID);
this.Dispatcher.Invoke(
new Action(() =>
{
LabelLive.Content = "Live :"; //Trying to refresh the label to put it over picturebox
}),
DispatcherPriority.ApplicationIdle);
}
I really don't know what to do to deal with this...
I have also tried ZPanels but nothing worked at the moment.
Thanks for your help !
I have an Ellipse in my WPF application. I want to change the colour of its outline whenever it is double clicked. I found this (old) tutorial about making this work by using the available MouseDown event and checking for a ClickCount of two in the event handler. This is the simplest solution to my problem and I'd like to try and get this to work before creating an empty button Control Template.
However, I'm unable to find the clicked ellipse in my code behind file. Supposedly this works in the tutorial, but I'm wondering if I'm missing anything.
Here's the code that contains the ellipse. It is the 3rd column of a grid:
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Column="3">
<StackPanel Orientation="Vertical" Margin="3,1" Background="GhostWhite">
<ItemsControl Name="FlowLinkItems" ItemsSource="{Binding FlowLinkList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="40">
<Ellipse Name="FlowLinkEllipse" Stroke="BlueViolet" Height="38" VerticalAlignment="Center" MouseDown="Ellipse_MouseDown"/>
<TextBlock TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Message}"></TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
In the tutorial, the code behind method worked like this:
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
FlowLinkEllipse.Stroke = "Red";
}
}
And the error I'm seeing is:
The name 'FlowLinkEllipse' does not exist in the current context
If this method is not possible I'm open to suggestions that are as simple as possible (I'm still new to WPF and the only thing my app will handle is this double click).
Note: I do have this line in my code behind and it works fine.
FlowLinkItems.MouseLeftButtonUp += FlowLinkItems_MouseLeftButtonUp;
As #Magus noted, you can't reference an item from code-behind, that is inside a DataTemplate. That should be no problem here, though: sender will contain a reference to the ellipse:
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
if (ellipse as sender == null || e.ClickCount < 2)
return;
var ellipse = (Ellipse)sender;
ellipse.Stroke = System.Windows.Media.Brushes.Red;
}
I use RibbonControlsLibrary. How to align one RibbonGroup to the right? It should be only one group in tab. All other groups should be aligned to the left.
You cannot align the RibbonGroup to the right. The Ribbon doesn't provide the ability to do this.
What you can do is to align page header items... but I don't know if it's enough for you:
DevExpress
I had the same issue, and I finally found something to do this :
I have 3 RibbonGroupBox. Groupe1 may be aligned on left, Groupe3 may be aligned on right. Groupe2 is just an empty RibbonGroupBox I inserted between Groupe1 and Groupe3.
Code XAML :
<Fluent:Ribbon DockPanel.Dock="Top" Title="{x:Static p:Resources.MiseEnBarre}" x:Name="mainRibbon">
<Fluent:RibbonTabItem x:Name="MainMenu" Header="{x:Static p:Resources.MainMenu}" SizeChanged="MainMenu_SizeChanged">
<Fluent:RibbonGroupBox x:Name="Groupe1">
<Fluent:Button x:Name="autoNest" SizeDefinition="Large" LargeIcon="img\image_bar_Nesting.png" Header="{x:Static p:Resources.MenuAutoNest}" Click="AutoNest_Click" />
<Fluent:Button x:Name="saveFile" SizeDefinition="Large" LargeIcon="img\image_save.png" Header="{x:Static p:Resources.MenuSauvegarder}" Click="Sauvegarder_Click" />
</Fluent:RibbonGroupBox>
<Fluent:RibbonGroupBox x:Name="Groupe2">
</Fluent:RibbonGroupBox>
<Fluent:RibbonGroupBox x:Name="Groupe3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=AvailableCNClist}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="1" Text="{Binding Path=AvailableCNClist2}" HorizontalAlignment="Right"/>
</Grid>
</Fluent:RibbonGroupBox>
</Fluent:RibbonTabItem>
</Fluent:Ribbon>
Then to manage the Windows redimensioning, I add on my main window the event SizeChanged="MainWindow_SizeChanged" (In the case your RibbonGroupBox dimensions could also change, just add the same event on them).
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateAlignRibbon();
}
private void UpdateAlignRibbon()
{
Groupe2.Width = MyWindow.ActualWidth - Groupe1.ActualWidth - Groupe3.ActualWidth;
}
In my case the Groupe3 RibbonGroupBox may change of dimension, so I call UpdateAlignRibbon() from 3 points :
After Initialization of my window(including defining the GroupBoxes content)
When the MainWindow has its dimensions changed
When Groupe1 or Groupe3 have its dimensions changed
Rover, You can try add RibbonGroup between last left RibbonGroup and Right align RibbonGroup and assign size to newly added ribbon related to window size.
example <RibbonGroup Width="400"></RibbonGroup>
it's looks following image
You can sort of hack in alignment but I'd recommend against it.
<r:RibbonGroup Header="This is a Filler Header With No Functionality but to Take Up Space" Visibility="Hidden">
<s:RibbonButton2/>
<s:RibbonButton2/>
<s:RibbonButton2/>
<s:RibbonButton2/>
</r:RibbonGroup>
The customer wanted their logo on the ribbon across the top of the page, but the more you add "false" elements to the bar, the quicker "true" elements will collapse when shrinking the window size.
Try this:
<RibbonTab Header="Home" x:Name="rtabHome" FlowDirection="RightToLeft" >
<RibbonGroup Header="Group">
<TextBlock Text="Example"/>
</RibbonGroup>
</RibbonTab>
Works with FlowDirection="RightToLeft".
I'd like to know if it is possible to define as the text of a Button in WPF, something like:
a b c
I've tried setting
alt text http://img651.imageshack.us/img651/1838/ctldhrzhy41gbrcch4dpjz4.png
but that doesn't seem to work.
Is it only possible to use the Bold tag with FlowDocuments?
Thanks
Use a TextBlock to hold the formatted text:
<Button>
<TextBlock>Hey <Bold>you</Bold>!!!</TextBlock>
</Button>
Per your comment, if you want to be explicit about the fact that this sets the Content property, you can use XAML property element syntax to do so:
<Button>
<Button.Content>
<TextBlock>Hey <Bold>you</Bold>!!!</TextBlock>
</Button.Content>
</Button>
However this is redundant because Button has a ContentPropertyAttribute which makes the first version exactly equivalent to the second anyway.
This will work.
<Grid>
<Button Name="button1" Width="40" Height="40"
Content="something" FontWeight="Bold" />
</Grid>
Try <Button><TextBlock>a<Bold>b</Bold>c</TextBlock></Button>.
The simpliest solution i could think of:
private void ButtonClick(object sender, RoutedEventArgs e)
{
string buttonText = (sender as Button).Content.ToString();
}