I'm working with an item template that should display one or more buttons per item. There are three buttons that I want to be displayed on a horizontal line. Each button has an icon and some text.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="LeftButton"
Text="Left Button"
ImageSource="left.png"
HorizontalOptions="Start"/>
<Button x:Name="CenterButton"
Text="Center Button"
ImageSource="center.png"
HorizontalOptions="Center"/>
<Button x:Name="RightButton"
Text="Right Button"
ImageSource="right.png"
HorizontalOptions="End"/>
</Grid>
This is working good so far. The three buttons display the icon and text and they are aligned left, center and right respectively.
Now, I want the buttons to only display the icons, if the container is not wide enough to display all the text. As far as I understand MVVM, this should be the responsibility of the View.
My intended solution would be something like this:
public partial class ItemTemplate : ContentView
// ContentView is our implementation of a UI element.
{
public ItempTemplate()
{
InitializeComponent();
SizeChanged += HandleSizeChanged;
}
private void HandleSizeChanged(object sender, EventArgs e)
{
if (/* not enough space */)
{
LeftButton.Text = string.Empty;
CenterButton.Text = string.Empty;
RightButton.Text = string.Empty;
}
else
{
LeftButton.Text = "Left Button";
CenterButton.Text = "Center Button";
RightButton.Text = "Right Button";
}
}
}
Is there any way to know if the container is wide enough for all three button? If possible, I'd like to use a dynamic solution, because the button text will eventually be translated.
You can place the code into a custom contentview, and decide to hide/show the text in the event LayoutChanged
according to the container's width.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="LeftButton" Grid.Column="0" Text="Left Button" ImageSource="dots.png" HorizontalOptions="Start"/>
<Button x:Name="CenterButton" Grid.Column="1" Text="Center Button" ImageSource="dots.png" HorizontalOptions="Center"/>
<Button x:Name="RightButton" Grid.Column="2" Text="Right Button" ImageSource="dots.png" HorizontalOptions="End"/>
</Grid>
public partial class MyView : ContentView
{
public MyView()
{
InitializeComponent();
this.LayoutChanged += MyView_LayoutChanged;
}
private void MyView_LayoutChanged(object sender, EventArgs e)
{
var view = sender as View;
if (view.Width < 200)
{
LeftButton.Text = string.Empty;
CenterButton.Text = string.Empty;
RightButton.Text = string.Empty;
}
else
{
LeftButton.Text = "Left Button";
CenterButton.Text = "Center Button";
RightButton.Text = "Right Button";
}
}
}
xmlns:local="clr-namespace:FormsApp"
<local:MyView/>
<Grid HorizontalOptions="Start" WidthRequest="199" >
<local:MyView/>
</Grid>
I solved my problem by using a custom button implementation (mostly because I needed some other additional features).
The custom button contains an Image and a Label. In addition to the standard button features I need, I added these methods to the code-behind:
public void ExpandText() {
Label.IsVisible = true;
}
public void CollapseText() {
Label.IsVisible = false;
}
public bool IsTextCollapsed() {
return !Label.IsVisible;
}
public double GetWidthAsExpanded() {
return Image.Width + Label.Width;
}
In the container's code-behind I check if the button's width fits within its container and collapse/expand accordingly. For that to work, I added containers for each button.
public ItemTemplate() {
InitializeComponent();
LayoutChanged += HandleLayoutChanged;
}
private static void HandleLayoutChanged(object sender, EventArgs e)
{
if (!(sender is ItemTemplate itemTemplate))
{
return;
}
if (itemTemplate.ButtonContainerLeft.Width > itemTemplate.ButtonLeft.GetWidthAsExpanded()
&& itemTemplate.ButtonContainerCenter.Width > itemTemplate.ButtonCenter.GetWidthAsExpanded()
&& itemTemplate.ButtonContainerRight.Width > itemTemplate.ButtonRight.GetWidthAsExpanded())
{
ExpandAllButtons(itemTemplate);
}
else
{
CollapseAllButtons(itemTemplate);
}
}
Because I added ExpandText
and CollapseText
earlier, I don't have to "remember" what the text inside the button was, because I just collapse the label within the button. GetWidthAsExpanded
will always return the necessary width of the button, even if it is collapsed.
side-note 1: I could've just added the width-check within the custom button implementation, but not every ItemTemplate
has all buttons and if any label is collapsed, all labels should be collapsed.
side-note 2: I needed button containers either way, because the left button will either be "Mark as Read" or "Mark as Unread" depending on the state of the ItemTemplate
data context. So there are actually two buttons in the first container.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.