Im having diffculty with datetime when its displayed client side from my rest web service, my client side wpf app code looks like this:
public MainWindow()
{
InitializeComponent();
string uriGroups = "http://localhost:8000/Service/Student";
XDocument xDoc = XDocument.Load(uriGroups);
foreach(var node in xDoc.Descendants("Student"))
{
GroupBox groupbox = new GroupBox();
groupbox.Header = String.Format(node.Element("StudentID").Value);
groupbox.Width = 100;
groupbox.Height = 100;
groupbox.Margin = new Thickness(2);
TextBlock textBlock = new TextBlock();
textBlock.Text = String.Format(node.Element("FirstName").Value + " " + (node.Element("LastName").Value));
textBlock.TextAlignment = TextAlignment.Center;
TextBlock textBlock1 = new TextBlock();
textBlock1.Text = String.Format(node.Element("TimeAdded").Value);
textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.VerticalAlignment = VerticalAlignment.Bottom;
StackPanel stackPanel = new StackPanel();
stackPanel.Children.Add(groupbox);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(textBlock1);
stackPanel.Margin = new Thickness(10);
MainArea.Children.Add(stackPanel);
}
}
And my service looks like this:
public class Student
{
....
public DateTime TimeAdded;
public string TimeAddedString
{
get
{
return this.TimeAdded.ToString("dd/MM/yyyy hh:mm:ss");
}
}
But the output looks like this:
Is there a way on my client side app code to truncate this or reformat it?
You can cast it to a DateTime and then use String.Format
Here is an example with one format you could use:
String.Format("{0:M/d/yyyy}", ((DateTime)node.Element("TimeAdded").Value))
You can also use DateTime.ToString(FORMAT)
((DateTime)node.Element("TimeAdded").Value).ToString("d");
I have made an assumption that .Value returns an object, but if it returns a DateTime then you can drop the casts.
If you are getting a string into your client, then you will need to use DateTime.Parse
(DateTime.Parse(node.Element("TimeAdded").Value)).ToString("d");
String.Format("{0:M/d/yyyy}", DateTime.Parse(node.Element("TimeAdded").Value))
You are using TimeAdded...but I think you should be using TimeAddedString
textBlock1.Text = String.Format(node.Element("TimeAdded").Value);
Should be
textBlock1.Text = String.Format(node.Element("TimeAddedString").Value);
I believe
Related
I'm wondering how I can get the contents of a stackpanel which has been added to a GridViewItem (YouTube data API, the stackpanel contains a bitmap image for a thumbnail, the title of the video and a hidden TextBlock with the video ID for reference).
To clarify, I need to be able to obtain the contents of the StackPanel that is contained in the GridViewItem (such as the string of that hidden TextBox) so I can use the data to display the correct video.
Here's the code I use to create the stackpanel.
public async Task SearchByKeyword(string searchTerm)
{
GeneralFunctions gf = new GeneralFunctions();
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = gf.YouTubeAPIKey,
ApplicationName = this.GetType().ToString()
});
var searchListRequest = youtubeService.Search.List("snippet");
searchListRequest.Q = searchTerm; // Replace with your search term.
searchListRequest.MaxResults = 50;
searchListRequest.SafeSearch = SearchResource.ListRequest.SafeSearchEnum.Strict;
// Call the search.list method to retrieve results matching the specified query term.
var searchListResponse = await searchListRequest.ExecuteAsync();
List<string> videos = new List<string>();
List<string> channels = new List<string>();
List<string> playlists = new List<string>();
// Add each result to the appropriate list, and then display the lists of
// matching videos, channels, and playlists.
foreach (var searchResult in searchListResponse.Items)
{
switch (searchResult.Id.Kind)
{
case "youtube#video":
// Create a new StackPanel to insert as a ListViewItem
StackPanel sPanel = new StackPanel();
sPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
sPanel.VerticalAlignment = VerticalAlignment.Stretch;
sPanel.Orientation = Orientation.Vertical;
sPanel.Width = 160;
sPanel.Height = 160;
// Create new StackPanel "Child" elements with alignment and width
TextBlock tb1 = new TextBlock();
tb1.Text = searchResult.Snippet.Title;
tb1.TextWrapping = TextWrapping.WrapWholeWords;
tb1.Width = 160;
// Create new StackPanel "Child" elements with alignment and width
TextBlock tb2 = new TextBlock();
tb2.Text = searchResult.Snippet.ChannelId;
tb2.TextWrapping = TextWrapping.WrapWholeWords;
tb2.Width = 160;
// Create new StackPanel child element for a 120x120 thumbnail of the videos from the search results
Image image = new Image();
image.Source = new BitmapImage(new Uri(searchResult.Snippet.Thumbnails.Default__.Url, UriKind.Absolute));
// Add a "hidden" child element to each stackpanel to hold the video identity
TextBlock h1 = new TextBlock();
h1.Text = searchResult.Id.VideoId.ToString();
h1.Visibility = Visibility.Collapsed;
h1.TextWrapping = TextWrapping.WrapWholeWords;
sPanel.Children.Add(image);
sPanel.Children.Add(tb1);
sPanel.Children.Add(tb2);
sPanel.Children.Add(h1);
SearchResults.Items.Add(sPanel);
break;
case "youtube#channel":
//SearchResults.Items.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.ChannelId));
break;
case "youtube#playlist":
//playlists.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.PlaylistId));
break;
}
}
//Console.WriteLine(String.Format("Videos:\n{0}\n", string.Join("\n", videos)));
//Console.WriteLine(String.Format("Channels:\n{0}\n", string.Join("\n", channels)));
//Console.WriteLine(String.Format("Playlists:\n{0}\n", string.Join("\n", playlists)));
}
Any help is appreciated.
Thanks
I guess I should never code tired right? The answer to my own question is actually very very simple
if (SearchResults.SelectedItems.Count > 0)
{
StackPanel sp = (StackPanel)SearchResults.SelectedItem;
TextBlock tb1 = (TextBlock)sp.Children[1];
TextBlock tb2 = (TextBlock)sp.Children[2];
TextBlock hf1 = (TextBlock)sp.Children[3];
}
At the moment, I have multiple textblocks which I want to access according to the name of the string. Look at the example below:
TextBlock test1 = new TextBlock();
TextBlock test2 = new TextBlock();
TextBlock test3 = new TextBlock();
TextBlock test4 = new TextBlock();
public static void changeValues()
{
string name = "test";
for (int i = 1; i < 5; i++)
{
[name + i].Text = "Wow";
}
}
As you can see, I am trying to access text1, text2, etc. The reason I am doing this is because the value of "name" could change at any time so I can re-use this code. I can also make "i < 5" be "i < number" and have the method take an int as one of the arguments. The problem of course is that this won't actually work. I need the string name to be a reference to the TextBlock that the name gives. Any help is appreciated!
#PetSerAl is saying:
var yourBlocks = new TextBlock[]
{
new TextBlock(),
new TextBlock(),
new TextBlock(),
new TextBlock()
};
foreach (var block in yourBlocks)
{
block.Text = "Wow";
}
How about Dictionary?
Dictionary<string, string> myDictionary=
new Dictionary<string, TextBlock>();
myDictionary.Add("name1", mytextBlock1);
myDictionary.Add("name2", mytextBlock2);
myDictionary["name1"] = new TextBlock();
var tBlock = myDictionary["name2"];
Detail here
I am currently working on a WPF project that uses Caliburn.Micro and have hit a snag I was hoping you could help with. I have a form that allows the user to add new fields to a separate form with the intention that these new fields will persist. I am able to create these controls dynamically with the following code:
Grid tmpOuterGrid = new Grid();
RowDefinition rowDefinition1 = new RowDefinition();
RowDefinition rowDefinition2 = new RowDefinition();
rowDefinition1.Height = new GridLength(45, GridUnitType.Star);
rowDefinition2.Height = new GridLength(55, GridUnitType.Star);
tmpOuterGrid.RowDefinitions.Add(rowDefinition1);
tmpOuterGrid.RowDefinitions.Add(rowDefinition2);
tmpOuterGrid.Margin = new Thickness(0,0,0,10);
Grid tmpInnerGrid = new Grid();
Grid.SetRow(tmpInnerGrid, 0);
tmpInnerGrid.Margin = new Thickness(10,0,0,5);
tmpInnerGrid.Opacity = 0;
DataTrigger d = new DataTrigger();
Binding b = new Binding("DisplayFieldName");
b.Source = _fieldNames[primaryNameBase + "FieldTextBox"];
d.Binding = b;
d.Value = true;
Storyboard sbEnter = new Storyboard();
DoubleAnimation opAnimShow = new DoubleAnimation(1,new Duration(new TimeSpan(0,0,0,1)));
Storyboard.SetTargetProperty(sbEnter, new PropertyPath(UIElement.OpacityProperty));
sbEnter.Children.Add(opAnimShow);
Storyboard sbExit = new Storyboard();
DoubleAnimation opAnimHide = new DoubleAnimation(0, new Duration(new TimeSpan(0, 0, 0, 1)));
Storyboard.SetTargetProperty(sbExit, new PropertyPath(UIElement.OpacityProperty));
sbExit.Children.Add(opAnimHide);
BeginStoryboard bsEnter = new BeginStoryboard { Storyboard = sbEnter, Name = "beginStoryboardEnter" };
BeginStoryboard bsExit = new BeginStoryboard { Storyboard = sbExit, Name = "beginStoryboardExit" };
d.EnterActions.Add(bsEnter);
d.ExitActions.Add(bsExit);
Style st = new Style(typeof(Grid));
st.Triggers.Add(d);
tmpInnerGrid.Style = st;
TextBlock tb = new TextBlock();
tb.Name = primaryNameBase + "FieldHeaderText";
tb.Foreground = new SolidColorBrush(Color.FromArgb(136,255,255,255));
tb.FontSize = 14;
tb.Style = (Style) App.Current.Resources["NexaLightTextBlock"];
tb.HorizontalAlignment = HorizontalAlignment.Center;
tb.Text = fieldTextBox.DisplayText;
Border underline = new Border();
underline.BorderThickness = new Thickness(0, 0, 0, 1);
underline.BorderBrush = new SolidColorBrush(Color.FromArgb(136,49,250,250));
underline.VerticalAlignment = VerticalAlignment.Bottom;
underline.HorizontalAlignment = HorizontalAlignment.Center;
Binding binding = new Binding
{
Source = tb,
Path = new PropertyPath("ActualWidth"),
};
underline.SetBinding(FrameworkElement.WidthProperty, binding);
tmpInnerGrid.Children.Add(tb);
tmpInnerGrid.Children.Add(underline);
LowBorderTextBox lbtb = new LowBorderTextBox();
lbtb.Name = primaryNameBase + "FieldTextBox";
Grid.SetRow(lbtb, 1);
lbtb.Width = 140;
lbtb.Margin = new Thickness(10,0,0,0);
lbtb.FontColor = new SolidColorBrush(Colors.White);
lbtb.DisplayFontSize = 22;
lbtb.Style = (Style) App.Current.Resources["NexaLightCustomTextBox"];
lbtb.DisplayText = fieldTextBox.DisplayText;
lbtb.LostFocus += FieldLostFocus;
tmpOuterGrid.Children.Add(tmpInnerGrid);
tmpOuterGrid.Children.Add(lbtb);
wrapPanel.Children.Add(tmpOuterGrid);
I would then like these new controls to be persisted through application shutdowns. The approach I was thinking of taking was serializing the object into xaml and storing that in a file, and then reading this file and deserializing it to obtain the control object again, which would be added to my surrounding WrapPanel. This is all fine and dandy except for one detail. The controls that are created have a style with a datatrigger that is bound to a property of a NoteField object, there being one NoteField object for each of these types of control. I was planning on serializing the NoteField objects as well, so that I could just pull them back and hope that the binding would still be intact, but they implement the PropertyChangedBase interface of the Caliburn.Micro framework, and the NotifyOfPropertyChange() method is not marked as serializable. Here is the NoteField class:
[Serializable]
class NoteField : PropertyChangedBase
{
private string _controlName;
private bool _displayFieldName;
public bool DisplayFieldName
{
get { return _displayFieldName; }
set
{
_displayFieldName = value;
NotifyOfPropertyChange(() => DisplayFieldName);
}
}
private string _fieldName;
public string FieldName
{
get { return _fieldName; }
set
{
_fieldName = value;
NotifyOfPropertyChange(() => FieldName);
}
}
public NoteField(string controlName, string displayText)
{
DisplayFieldName = false;
_controlName = controlName;
FieldName = displayText;
}
public string GetControlName()
{
return _controlName;
}
public void SetControlName(string name)
{
_controlName = name;
}
}
I am not attached to using this class, but it was the only way I could think of having dynamically generated properties to bind to from the xaml. So, I guess my question is: is there a way that I can dynamically create controls that have bindings in them that can persist through application shutdowns? Am I on the right track, or should I do something else all together? Any help would be greatly appreciated. Thank you so much for your time.
I would like to have string containing Inline markups like
var str = "foo bar <Bold>dong</Bold>"
and feed TextBlock with it so the text would get formatted like it would be added to Inlines collection. How could I achive that?
You could wrap the text with a <TextBlock> tag and parse the whole thing as XAML:
public TextBlock CreateTextBlock(string inlines)
{
var xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"
+ inlines + "</TextBlock>";
return XamlReader.Parse(xaml) as TextBlock;
}
Then use the newly created TextBlock as you like. Put it in some Panel
var str = "foo bar <Bold>dong</Bold>";
grid.Children.Add(CreateTextBlock(str));
or perhaps copy its Inlines to another TextBlock.
You can try the below code.
<TextBlock x:Name="txtBlock"/>
string regexStr = #"<S>(?<Str>.*?)</S>|<B>(?<Bold>.*?)</B>";
var str = "<S>foo bar </S><B>dong</B>";
Regex regx = new Regex(regexStr);
Match match = regx.Match(str);
Run inline = null;
while (match.Success)
{
if (!string.IsNullOrEmpty(match.Groups["Str"].Value))
{
inline = new Run(match.Groups["Str"].Value);
txtBlock.Inlines.Add(inline);
}
else if (!string.IsNullOrEmpty(match.Groups["Bold"].Value))
{
inline = new Run(match.Groups["Bold"].Value);
inline.FontWeight = FontWeights.Bold;
txtBlock.Inlines.Add(inline);
}
match = match.NextMatch();
}
Is there a way to order stackpanels based on some of its child elements?
In the code behind I add some generic things like groupbox and textblock to a stackpanel, one of the textblocks information is DateTime from my webservice, I have tryed sorting via descending order using linq but the output is still the same.
So I was wondering if its possible to sort by one of the stackpanels child elements namely the textblock1.Text that holds the DateTime attribute?
XDocument xDoc = XDocument.Load(uriGroups);
var sortedXdoc = xDoc.Descendants("Student")
.OrderByDescending(x => Convert.ToDateTime(x.Element("TimeAdded").Value));
foreach (var node in xDoc.Descendants("Student"))
{
GroupBox groupbox = new GroupBox();
groupbox.Header = String.Format(node.Element("StudentID").Value);
groupbox.Width = 100;
groupbox.Height = 100;
groupbox.Margin = new Thickness(1);
TextBlock textBlock = new TextBlock();
textBlock.Text = String.Format(node.Element("FirstName").Value + " " + (node.Element("LastName").Value));
textBlock.TextAlignment = TextAlignment.Center;
TextBlock textBlock1 = new TextBlock();
textBlock1.Text = (DateTime.Parse(node.Element("TimeAdded").Value)).ToString("d");
String.Format("{0:d/M/yyyy}", DateTime.Parse(node.Element("TimeAdded").Value));
textBlock1.TextAlignment = TextAlignment.Center;
textBlock1.VerticalAlignment = VerticalAlignment.Bottom;
StackPanel stackPanel = new StackPanel();
stackPanel.Children.Add(groupbox);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(textBlock1);
stackPanel.Margin = new Thickness(5);
stackPanel.MouseEnter += new MouseEventHandler(stackpanel_MouseEnter);
stackPanel.MouseLeave += new MouseEventHandler(stackpanel_MouseLeave);
MainArea1.Children.Add(stackPanel);
}
}
The order of display is totally defined by the order of calls to
MainArea1.Children.Add(stackPanel);
So, try something like
foreach (var node in xDoc.Descendants("Student").OrderBy(e => ...))
{
....
}
(And you really should be using Temlates here)