1

When trying to change background of TextBlock that is part of a DataTemplate of a ListBox the background is only around the text and not the entire block

In UWP TextBlock doesn't have background property so I've wrapped it in a border and changed the border's background like this:

<ListBox x:Name="BitsListView" ItemsSource="{x:Bind BitsList, Mode=TwoWay}" Loaded="BitsListView_Loaded"
    HorizontalAlignment="Left" IsEnabled="{x:Bind IsWriteAccess,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
    SelectionChanged="BitsListView_SelectionChanged " SelectionMode="Single">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border>
                <StackPanel Orientation="Horizontal">
                    <TextBlock x:Name="BitText" Text="{Binding}" Loaded="BitText_Loaded" />
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>

And the color is changed in an OnLoaded event like this:

    private void BitText_Loaded(object sender, RoutedEventArgs e)
    {
        TextBlock bitText = sender as TextBlock;

        StackPanel sp = bitText.Parent as StackPanel;
        Border border = sp.Parent as Border;

        if ((int)bitText.DataContext == 1)
        {
            bitText.Foreground = new SolidColorBrush(Windows.UI.Colors.LightGreen);
            border.Background = new SolidColorBrush(Windows.UI.Colors.DarkGreen);

        }
        else
        {
            bitText.Foreground = new SolidColorBrush(Windows.UI.Colors.Gray);
            border.Background = new SolidColorBrush(Windows.UI.Colors.LightGray);
        }
    }

But the result is this: https://pasteboard.co/IlcZB1J.png

What i'm trying to achive is something like this: (Don't mind the bad MSPaint job)

https://pasteboard.co/Ild1plp.png

What i've tried to do to solve this is wrapping the stackpanel with border, but that didnt help. then i've tried to wrap the datatemplate but that is not possible, climbing further up the tree changing the backgrounds is not working properly, and obviously changing the ListBox's background paints the entire list, and I need only the blocks that has 1 to be painted fully and not just a little bit around the text

hem
  • 1,012
  • 6
  • 11
dima kal
  • 29
  • 1
  • 10

1 Answers1

1

For your question, you do not need to use border to wrap the StackPanel, it will not work. You just need to define a style for ListBoxItem and apply it to ItemContainerStyle and set HorizontalContentAlignment=Stretch.

Here, I checked your code. I have some suggestions for you. In UWP, you could do most things with binding. That means you do not need to find the specific control and set its property value from DataTemplate in the page's code-behind. It's not best practice. Instead, you could define a custom class which includes three properties(text,background,foreground). Then, you could bind to these properties on your XAML page.

The complete code sample like the following:

<ListView x:Name="BitsListView" ItemsSource="{x:Bind BitsList, Mode=TwoWay}"
HorizontalAlignment="Left" SelectionMode="Single">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                <Setter Property="Padding" Value="0"></Setter>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" ></StackPanel>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Test">
                <StackPanel Background="{x:Bind backGround}">
                    <TextBlock x:Name="BitText" Text="{x:Bind content}" Foreground="{x:Bind foreGround}" HorizontalTextAlignment="Center"/>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
public class Test : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private int _content;

    public int content
    {
        get { return _content; }
        set
        {
            if (_content != value)
            {
                _content = value;
                if (value == 1)
                {
                    foreGround = new SolidColorBrush(Colors.LightGreen);
                    backGround = new SolidColorBrush(Colors.DarkGreen);
                }
                else
                {
                    foreGround = new SolidColorBrush(Colors.Gray);
                    backGround = new SolidColorBrush(Colors.LightGray);
                }
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("content"));
            }
        }
    }

    private SolidColorBrush _backGround;

    public SolidColorBrush backGround
    {
        get { return _backGround; }
        set
        {
            if (_backGround != value)
            {
                _backGround = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("backGround"));
            }
        }
    }

    private SolidColorBrush _foreGround;

    public SolidColorBrush foreGround
    {
        get { return _foreGround; }
        set
        {
            if (_foreGround != value)
            {
                _foreGround = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("foreGround"));
            }
        }
    }
}
public sealed partial class MainPage : Page
{
    private ObservableCollection<Test> BitsList { get; set; }

    public MainPage()
    {
        this.InitializeComponent();
        BitsList = new ObservableCollection<Test>();
        for (int i = 0; i < 10; i++)
        {
            Random random = new Random();
            BitsList.Add(new Test() { content = random.Next(0, 9) });
        }
    }
}
Xie Steven
  • 8,544
  • 1
  • 9
  • 23
  • Are you sure your solution works? Because i've tried to implement it in my code and it didn't work at all, then I've tried running it in a sandbox and the items were in a vertical order, so i've added: ` ` but the result was still the same as my original post: https://pasteboard.co/IlkwNc2.png – dima kal Jun 27 '19 at 09:11
  • @dimakal Yes. My code did work for me. See [Screenshot](https://1drv.ms/u/s!AoI4pKdRYn8KnG-wod79Y1h8ux32?e=OVCC9k). You did not tell that you set ` ` in your original post. Please see my updated reply. Please use the ListView control and add `` in ItemContainerStyle. See [Screenshot](https://1drv.ms/u/s!AoI4pKdRYn8KnQmdoqPjMCRDOfTy?e=jObGQR) – Xie Steven Jun 27 '19 at 09:58
  • The problem is that its still not coloring it fully, when hovering/clicking the item there is a grayish border around the item like this: https://pasteboard.co/IllI163.png – dima kal Jun 27 '19 at 12:10
  • Also the use of list view is bad for me because it refreshes the whole list of objects when im clicking the items in the list, and it does not look good – dima kal Jun 27 '19 at 13:50
  • @dimakal `The problem is that its still not coloring it fully, when hovering/clicking the item there is a grayish border around the item` It's because the default ListViewItem's style has set the ``, you just need to set the `Padding=0`, then this issue will be resolved. See my updated reply. – Xie Steven Jun 28 '19 at 01:31
  • You could follow the [Theme resources in the resource dictionary structure](https://learn.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-theme-resources#theme-resources-in-the-resource-dictionary-structure) to find the 'generic.xaml' and view the default listviewitem style 'x:key=ListViewItemRevealStyle'. Then, you will know the reason. – Xie Steven Jun 28 '19 at 01:32
  • @dimakal `Also the use of list view is bad for me because it refreshes the whole list of objects when im clicking the items in the list, and it does not look good` This is a new question, please post a new thread. – Xie Steven Jun 28 '19 at 01:35
  • it’s not a new question because in my question I’m using listbox, and the question was regarding listbox, can this be done with listbox or do I have to use list view? – dima kal Jun 28 '19 at 07:57
  • @dimakal You certainly could use ListBox. You just need to change all 'ListView' to ListBox in my above XAML code. But I suggested that you read [ListBox vs. ListView and GridView](https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.listbox#listbox-vs-listview-and-gridview) and [Difference between ListView and ListBox in Visual Studio](https://stackoverflow.com/questions/13879720/difference-between-listview-and-listbox-in-visual-studio) to choose the right control in your UWP app. – Xie Steven Jun 28 '19 at 09:14
  • @dimakal `Also the use of list view is bad for me because it refreshes the whole list of objects when im clicking the items in the list, and it does not look good` As I said, this is a new question. Why? Because your original question is about 'ListBox XAML layout in UWP'. But this issue is about 'it refreshes the whole list of objects when im clicking the items in the list, and it does not look good', It's really a new question. You might have done some refresh operations in your code. But I did not care about it. For your current XAML layout issue, have you resolved it by my suggestions? – Xie Steven Jun 28 '19 at 09:23
  • It seems to work now after setting the padding to 0 and also adding Width to compensate for the lack of padding. now there is only one problem left, the text of the number inside the container is aligned to the left while i need it to be aligned to the center. Ofcourse chaging `` to center will not solve it, and adding `HorizontalTextAlignment="Center"` to the TextBlock does not do anything. – dima kal Jun 30 '19 at 07:56
  • @dimakal Please set `HorizontalTextAlignment="Center"` for the TextBlock in 'DataTemplate' to make the text aligne to the center. – Xie Steven Jul 01 '19 at 01:54
  • I've mentioned that i've tried it and it didn't work – dima kal Jul 01 '19 at 07:02
  • @dimakal It did work on my side. See [screenshot](https://1drv.ms/u/s!AoI4pKdRYn8KnG-wod79Y1h8ux32?e=1NyAxM). – Xie Steven Jul 01 '19 at 07:53
  • wow thats really odd, ive added like this `` and nothing happens – dima kal Jul 01 '19 at 08:01