How I can bind textblock with bolded and normal text - c#

I have a part of text which some of the words are formatted.
These text are listed in a ListBox. When user clicks ListBoxitem, I want to collect that selectedItem and take user to the other place. My problem is that I cant bind TextBlock with another instance of TextBlock. And that TextBlock has many inlines, which I want to show.
I have been trying this solution:
<ListBox Width="800" Name="foundedTextBlocksListBox" SelectionChanged="foundedTextBlocksListBox_SelectionChanged" Background="Transparent" ItemsSource="{Binding}" Grid.Row="2" Visibility="Visible" Height="Auto" HorizontalAlignment="Center">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
<TextBlock x:Name="foundedTextBlocks" DataContext="{Binding Textblock}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After Binding to DataContext like this:
ObservableCollection<FoundedTextBlock> listOfFoundedTextBlockResults = new ObservableCollection<FoundedTextBlock>();
TextBlock textblock = new TextBlock();
while (blockString.IndexOf("<b>") != -1)
{
int startOfWord = blockString.IndexOf("<b>");
int endOfWord = blockString.IndexOf("</b>");
string text = blockString.Substring(0, startOfWord);
textblock.Inlines.Add(text);
string boldedWord = blockString.Substring(startOfWord + 3, endOfWord - startOfWord - 3);
textblock.Inlines.Add(new Run() { Text = boldedWord, FontWeight = FontWeights.Bold });
blockString = blockString.Substring(endOfWord + 4);
textblock.Inlines.Add(blockString);
}
textblock.Tag = dbInfo;
listOfFoundedTextBlockResults.Add(new FoundedTextBlock() { Textblock = textblock });
}
foundedTextBlocksListBox.DataContext = listOfFoundedTextBlockResults;
I can't see any ListBoxItems in ListBox. Is my Binding wrong or is this possible at all?
I managed before to get TextBlock.Text property to show but not the Inlines where are bolded text or any other Inlines after my first inline addition to TextBlock.
How I can solve this annoiyng problem? In short, I need to display many TextBlocks with formatted text...
FoundedTextBlock class has TextBlock textblock {get;set;} property
I'm saving to Tag property my class instance, so I could collect the information I need when SelectedValueChanged event occurs.

Maybe you should use a ContentPresenter instead of TextBlock in your XAML
Replace
<TextBlock x:Name="foundedTextBlocks" DataContext="{Binding Textblock}"></TextBlock>
with
<ContentPresenter Content="{Binding Textblock}" />
Please try it out ... the rest of your code is missing to provide a better answer.

Related

Dynamically added controls in stackpanel is not visible in wpf c#

I am dynamically adding textboxes based on a button click inside the stackpanel.But the textboxes are not visible in the UI .
Here is the code used for creating textboxs inside stackpanel.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
}
why its not visible..??and here is the XAML part of stackpanel
<StackPanel Name="panel1" Grid.Column="1" HorizontalAlignment="Left" Height="151" Margin="427,60,0,0" Grid.Row="2" VerticalAlignment="Top" Width="216">
<StackPanel Height="144">
</StackPanel>
</StackPanel>
If you are going to be adding controls dynamically, do not restrict the height (or even width) of the container you are adding to.
Update your XAML to have auto height/width.
<StackPanel Name="panel1"
Grid.Column="1"
Height="Auto"
Width="Auto"
Margin="427,60,0,0"
Grid.Row="2"
VerticalAlignment="Top"
HorizontalAlignment="Left" >
<StackPanel Height="144">
</StackPanel>
</StackPanel>
Also, once you add a new child, make sure you are updating the StackPanel layout.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
panel1.UpdateLayout();
}
In your xaml code, there is a stackpanel in your 'panel', it will be the 1st child of 'panel'.
And its height is 144px. your 'panel1' is 151 px.
So when you add textboxes into 'panel', they will be displayed behind the 144px stackpanel.
There is only 7px to display them. So they will not display on your window.

Stackpanel "breaks" and has black background when the content is side is too much

I have the follow XAML:
<ContentControl HorizontalAlignment="Left" HorizontalContentAlignment="Left" Content="{Binding TotalReviewWordBlock}" Width="465" Margin="5,10,0,5" Foreground="#FF2D2D2D" Background="White"/>
and its binded to the following property:-
public StackPanel TotalReviewWordBlock
{
get
{
StackPanel st = new StackPanel();
st.Orientation = Orientation.Horizontal;
st.Background = new SolidColorBrush(Colors.White);
Paragraph pgf = new Paragraph();
Run r = new Run();
r.Text = App.Convert("Blah ");
r.FontWeight = FontWeights.Bold;
r.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(r);
int Rating = (int)(this.userrating * 2);
string ratingReplacement;
(some more code in the property itself...)
Run run = new Run();
run.Text = " " + this.myText;
run.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(run);
RichTextBox rtb = new RichTextBox();
rtb.TextWrapping = TextWrapping.Wrap;
rtb.Width = 450;
rtb.Blocks.Add(pgf);
st.Children.Add(rtb);
st.Background = new SolidColorBrush(Colors.White);
return st;
}
}
The problem is when the text is too much(say more that a 1000 character), or the height of the stackpanel is a lot, Its background becomes black. Its as if the stackpanel breaks) I noticed this earlier but at that time it was in a listbox and had multiple items to i simply made the width of each item 480, used blank grids instead of margins and it was "covered". But this time its just one big chunk of text(in a Paragraph). Let me know if you need ay other info. Please help!!
I worked around a similar "black stackpanel" problem by splitting the text into paragraphs to form a List<String>. And then that list of strings would be the ItemsSource of a ListBox.
So instead of a very large StackPanel, I ended up with a long ListBox.
I also prevented user interaction in the ListBox and vertical scroll by using IsHitTestVisible="False" and ScrollViewer.VerticalScrollBarVisibility="Disabled"
So, the ListBoxended up as follows:
<ListBox x:Name="listBox" IsHitTestVisible="False" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="White">
<TextBlock TextWrapping="Wrap" Text="{Binding}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in code behind:
textSplitInParagraphs = new List<String>();
// add paragraphs to the list...
listBox.ItemsSource = textSplitInParagraphs;
Don't know if it is the correct workaround, but I helped me, after some time of banging my head against the table.
Hope this helps.

Changing from xaml design into C# coding

I am currently try to programatically get the ListBox
I tried to find many ways but, I can't make this works.
Here is the xaml part of code:
<ListBox Grid.Row="2" Grid.ColumnSpan="2" x:Name="PeerList" Margin="10,10,0,10">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" FontSize="{StaticResource PhoneFontSizeMedium}" Margin="40,0,0,0"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want this same operation to be done programatically.
Someone familiar to XAML to C# help me to solve this. .
It is something like this
ListBox listbox = new ListBox();
DataTemplate dataTemplate = new DataTemplate();
FrameworkElementFactory elementFactory = new FrameworkElementFactory(typeof(TextBlock));
elementFactory .SetBinding(TextBlock.TextProperty, new Binding("DisplayName"));
dataTemplate.VisualTree = elementFactory;
listbox.ItemTemplate = dataTemplate ;
If you want Programatically display the name of the peers in this list means follow #Hiệp Lê Answer.
Otherwise if you want only to get the name of the peers. Just follow this.
void SearchPeers()
{
List<string> name = new List<string>();
var peers = await PeerFinder.FindAllPeersAsync();
for(int i=0;i<peers.Count;i++)
{
string peerName = peers.DisplayName;
name.Add(peerName);
}
}
This will get you the name of the peers available.

WPF Get CheckBoxes inside ListBox in code

I have this List box and I want to search for its items which were selected (IsChecked=true) by user
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}"
Name="chkBoxSelectAllStaff" Content="Select All">
</CheckBox>
<ListBox Name="lstStaffs" MaxHeight="250" MinHeight="50" Margin="0,5,5,5" Width="350"
ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Right"
HorizontalContentAlignment="Right">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}" IsChecked="{Binding ElementName=chkBoxSelectAllStaff, Mode=OneWay, Path=IsChecked}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding LastName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding CellphoneNumber}" Margin="0,0,3,0"></TextBlock>
</StackPanel>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
I want to do something like this
foreach(var item in lstStaff.Items){
if((CheckBox) item).IsChecked){
//do something
}
}
And also I am binding the data this way :
//staff is my entity object containing Id, FirstName, LastName, CellphoneNumber
lstStaffs.ItemsSource = args.Result; // comes from webservice call and is Staff[]
lstStaffs.UpdateLayout();
But I get Staff object in lstStaffs.Items!!, So how can I iterate over selected(IsChecked=true) items(staffs) ...
Tnx
From the How to: Find DataTemplate-Generated Elements page at MSDN:
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.
ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock",
myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: "
+ myTextBlock.Text);
This shows you how to get access to elements defined in a DataTemplate. However, if you just want to get access to the items from the collection that have been selected, there is a much simpler way:
var selectedItems = lstStaffs.SelectedItems;
You must set the SelectionMode to Multiple or Extended for this to work.

Can't change gridview itemssource

I'm trying to change a box's color in a gridview(that has ItemTemplates which has 100 green boxes).
First, I created a list(which typed as my class) and I added all items to list and I added list to my gridview source :
grid1.ItemsSource = boxlist;
After, I added a click event for item click on gridview. I want that when I clicked to an item, this item's color will be changed. So I edited list as it :
int id = ((Boxes)e.ClickedItem).id;
boxlist[id].color = "DarkRed";
grid1.ItemsSource = boxlist;
I tried it to change color of clicked item but it doesn't work. Color of list item is changing succesfully but gridview is not taking it. But I want that gridview takes this new source. How can I solve this problem?
My class :
class Boxes
{
public int id { get; set; }
public string color { get; set; }
}
XAML of GridView
<GridView x:Name="grid1" HorizontalAlignment="Left" Margin="354,41,0,0" VerticalAlignment="Top" Width="800" Height="650" SelectionMode="None" IsItemClickEnabled="True" ItemClick="grid1_ItemClick">
<GridView.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid Height="50" Width="50">
<Rectangle x:Name="rect1" Width="50" Height="50" Fill="{Binding color}" Tag="{Binding id}"/>
</Grid>
</DataTemplate>
</GridView.Resources>
<GridView.ItemTemplate>
<StaticResource ResourceKey="DataTemplate1"/>
</GridView.ItemTemplate>
</GridView>
You have to null the ItemSource just before you set the new value:
ctlList.ItemsSource = null;
ctlList.ItemsSource = YourObjects;
I recommand to use DataContext and Binding instead of your solution:
http://www.codeproject.com/Articles/30905/WPF-DataGrid-Practical-Examples
You need to use DataContext instead like this:
grid1.DataContext = boxlist;

Categories

Resources