I have the following xaml
<StackPanel x:Name="StackPanelBanner" Grid.Row="1"></StackPanel>
I had to write this much messy code to add picture to it.
var toplogoBitmap = new BitmapImage();
toplogoBitmap.BeginInit();
toplogoBitmap.UriSource = new Uri(#"" + _appPath + "images/toplogo.png", UriKind.RelativeOrAbsolute);
toplogoBitmap.EndInit();
var toplogoImage = new Image
{
Source = toplogoBitmap,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Stretch = Stretch.None
};
StackPanelBanner.Children.Add(toplogoImage);
Because i have to get the images from folder, which will be changing on time to time, i can't put them in resources.
Is there any short way of adding picture in XAML control. i.e
<StackPanel source="toplogo" x:Name="StackPanelBanner" Grid.Row="1"></StackPanel>
in Codebehind
var toplogo = #"" + _appPath + "images/toplogo.png";
Your "messy" code is pretty much the code you would need to add an item to a content control. You can't really shorten it, but if you're doing this regularly, refactoring to a method could help reduce the extra code required:
public void AddImageToContainer(string path, Panel parent)
{
var bmap = new BitmapImage(new Uri(_appPath + path, UriKind.RelativeOrAbsolute));
var img = new Image
{
Source = bmap,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Stretch = Stretch.None
};
parent.Children.Add(img);
}
You could then just call this as needed, ie:
AddImageToContainer("images/toplogo.png", StackPanelBanner);
You could use an ItemsControl that uses a StackPanel as its ItemsPanel.
<ItemsControl x:Name="itemsControl" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You might now add images as easy as shown below, because WPF provides built-in type conversion from string (or Uri) to ImageSource:
itemsControl.Items.Add(_appPath + "images/toplogo.png");
Related
I am still a newbie to VS, C# and XAML. I have this XAML code
<ListBox Background="Black" x:Name="ListBox1" Width="900" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Width="{Binding ElementName=ListBox1, Path=Width}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Now I want to create and add another child control to the ListBox control using c#. I use this code below to create a ListBoxItem control
ListBoxItem li = new ListBoxItem();
li.Background = Brushes.White;
li.Width = 150;
li.Height = 200;
Thickness margin = li.Margin;
margin.Left = 5;
margin.Right = 5;
margin.Top = 5;
margin.Bottom = 5;
li.Margin = margin;
li.VerticalAlignment = System.Windows.VerticalAlignment.Top;
li.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
Then I also use this code to append the newly created ListBoxItem to the ListBox control
ListBox1.Controls.Add(li);
But its not working. I don't know what am getting wrong
This code works for me
ListBox1.Items.Add(li);
First I want to appologize for so much code, but English is not my native language so I put as much details as I could, and hope that you will understand what my problem is.
Also I just started learning C# 20 days ago so my error will probably be some basic newbie error :)
Anyway, I have WPF form with few Grids, and in one of the Grid there is:
<Grid Grid.Column="2" Grid.Row="1" Name="grdPLUPanel" >
<ItemsControl x:Name="btnPLUList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" Margin="0"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content ="{Binding Content}" Height="{Binding Height}" Width="{Binding Width}" Tag="{Binding Tag}" Margin="{Binding Margin}" Background="{Binding Color}" FontSize="{Binding FontSize}" FontWeight="Medium" HorizontalAlignment="Center" Click="ClickHandlerGrp" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
All of those Bindings Works perfectly except for Background="{Binding Color}".
Code for assigning color which I am getting from database as int (ie. -32768), then converting to Hex(#FFFF8000) and adding to the Background is:
if (dictPLU.ContainsKey(Convert.ToString(i)))
{
GetPLURowsFromDB.MyObject valuePLU = dictPLU[Convert.ToString(i)];
byte[] bytes = BitConverter.GetBytes(valuePLU.btnColor);
var newColor = new SolidColorBrush(Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]));
btns.Add(new TodoItem() { Content = valuePLU.btnContent, Height = btnMinimumHeightSize, Width = btnMinimumWidthSize, FontSize = fntSize, Tag = valuePLU.btnPLUID, Background = newColor, Margin = "1," + separationX + ",0,0" });
}
else
{
btns.Add(new TodoItem() { Content = "", Height = btnMinimumHeightSize, Width = btnMinimumWidthSize, Tag = "PLU" + Convert.ToString(i), Margin = "1," + separationX + ",0,0" });
}
Above code doesn't work, also there are no errors, Button Background simply does not change.
When debugging:
newColor is (#FFFF8000)
valuePLU is (-32768)
Background is {#FFFFFFFF} - a default color assigned automatically when buttons are created.
However if i put Button (btnRcptESC) manually on the form, and use following code:
private void MainWindowView_OnLoaded(object sender, RoutedEventArgs e)
{
byte[] bytes = BitConverter.GetBytes(Convert.ToInt32("-32768"));
var colorNew = new SolidColorBrush(Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]));
btnRcptESC.Background = colorNew;
}
Button Will Change Color.
I am suspecting that problem is in Constructor "public SolidColorBrush Background { get; set; }"
Maybe SolidColorBrush is not proper type?
I've figured out, the problem was in XAML (Background="{Binding Color}" ) and Constructor (public SolidColorBrush Background { get; set; }).
For this to work correctly, in XAML should be (Background="{Binding Background})"
As I said, this is probably noob error :)
Thank you all!
I've got a weird problem with a listbox, which is placed in a custommessagebox.
Problem: You can't scroll down the list, because a "draggesture" up does the same thing than down. So the only thing I got is the respond-animation when your at the top of the list.
I made a little sample:
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Background="Bisque" Content="Click Me" Click="Button_Click"></Button>
</Grid>
</Grid>
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var source = new string[200];
for (int i = 0; i < source.Length; i++)
{
source[i] = i.ToString();
}
var dialog = new CustomMessageBox()
{
Content = new ListBox(){ItemsSource = source},
RightButtonContent = "Cancel",
LeftButtonContent = "Store",
VerticalContentAlignment = VerticalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = HorizontalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
dialog.Show();
}
}
And here is the link, if you wanna download it:
https://onedrive.live.com/redir?resid=6B27FD720F1FB58D!15988&authkey=!ACG5krcfzsoBxA8&ithint=folder%2csln
Does anyone has an idea whats going wrong?
Thx for any help.
There is a simple fix for that.. Add a Height to the ListBox. Like this.
var dialog = new CustomMessageBox()
{
Content = new ListBox(){ItemsSource = source, Height = 800},
RightButtonContent = "Cancel",
LeftButtonContent = "Store",
VerticalContentAlignment = VerticalAlignment.Top, // Change to Top
VerticalAlignment = VerticalAlignment.Top, // Change to Top
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = HorizontalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
Change the VerticalContentAlignment and VerticalAlignment to Top so when you set the Height value less than 800 the content is aligned to the top.
just you need to add height for listbox as :
Content = new ListBox(){ItemsSource = source,Height=800}
I do not recommend setting the height, as Daniel Z mentioned you'll lose adaptive design. I managed a better workaround and it worked perfectly for me without setting the height to a static value.
Put the content of the CustomMessageBox in a UserControl. Suppose the xaml content of this control looks like this
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
<!-- your listbox and content here -->
</Grid>
in the code behind, implement the loaded event:
public UserControl1()
{
InitializeComponent();
this.Loaded += UserControl1_Loaded;
}
void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
LayoutRoot.Height = (this.Parent as CustomMessageBox).ActualHeight;
}
By setting the height of the grid, your listbox will automatically adjust its height to fit in. Hope it helps.
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.
I am creating Dynamic Rectangle and adding into StackPanel. I need to add text to each rectangle. How can I do that?
A Rectangle doesn't have any child content, so you will need to put both controls inside of another panel, such as a grid:
<Grid>
<Rectangle Stroke="Red" Fill="Blue"/>
<TextBlock>some text</TextBlock>
</Grid>
You can also use a Border control, which will take a single child and draw a rectangle around it:
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock>some text</TextBlock>
</Border>
You say "dynamic rectangle", so it sounds like you are doing this in code. The equivalent C# would look something like this:
var grid = new Grid();
grid.Children.Add(new Rectangle() { Stroke = Brushes.Red, Fill = Brushes.Blue });
grid.Children.Add(new TextBlock() { Text = "some text" });
panel.Children.Add(grid);
// or
panel.Children.Add(new Border()
{
BorderBrush = Brushes.Red,
BorderThickness = new Thickness(1),
Background = Brushes.Blue,
Child = new TextBlock() { Text = "some text" },
});
But if you want a dynamic list of rectangles, you should probably use an ItemsControl:
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock Text="{Binding Text}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you set the DataContext to a list of objects, this XAML will create a Border with a TextBlock for each one with the text set to the Text property on the object.
First of all you can do this, but not by adding the control. And there is a very good reason to do this, for high speed hardware rendering. You can create a special brush from a UI element that caches itself in hardware and fill the rectangle with this hardware, and it is extremely fast. I will just show the code behind because it is the example I have offhand
Rectangle r = new Rectangle();
r.Stroke = Brushes.Blue;
r.StrokeThickness = 5;
r.SetValue(Grid.ColumnProperty, 1);
r.VerticalAlignment = VerticalAlignment.Top;
r.HorizontalAlignment = HorizontalAlignment.Left;
r.Margin = new Thickness(0);
r.Width = 200;
r.Height = 200;
r.RenderTransform = new TranslateTransform(100, 100);
TextBlock TB = new TextBlock();
TB.Text = "Some Text to fill";
// The next two magical lines create a special brush that contains a bitmap
// rendering of the UI element that can then be used like any other brush
// and it's in hardware and is almost the text book example for utilizing
// all hardware rending performances in WPF unleashed 4.5
BitmapCacheBrush bcb = new BitmapCacheBrush(TB);
r.Fill = bcb;
MyCanvas.Children.Add(r);
You need to add a textual control to your StackPanel, such as Label or TextBlock.