Customizing My app W10 Template from AppStudio
Hello everyone, I’m new to programming and I wanted to make a Windows App just for fun, so far it looks good, however. I have a problem (mostly because I don’t know what I’m doing).
But I want the RSS feed to open Edge instead of the feed view (second page after you click on a feed icon)
I found the config file for the rss feed ( I called it news) but I don’t know how to make it open a new window on edge .
The code is located at:
Sections\NewsConfig.cs
Update: This is the full original code:
using System;
using System.Collections.Generic;
using AppStudio.DataProviders;
using AppStudio.DataProviders.Core;
using AppStudio.DataProviders.Rss;
using AppStudio.Uwp.Actions;
using AppStudio.Uwp.Commands;
using AppStudio.Uwp.Navigation;
using MyWindows10App.Config;
using MyWindows10App.ViewModels;
namespace MyWindows10App.Sections
{
public class NewsConfig : SectionConfigBase<RssDataConfig, RssSchema>
{
public override DataProviderBase<RssDataConfig, RssSchema> DataProvider
{
get
{
return new RssDataProvider();
}
}
public override RssDataConfig Config
{
get
{
return new RssDataConfig
{
Url = new Uri("https://localhost:804514/feed")
};
}
}
public override NavigationInfo ListNavigationInfo
{
get
{
return NavigationInfo.FromPage("NewsListPage");
}
}
public override ListPageConfig<RssSchema> ListPage
{
get
{
return new ListPageConfig<RssSchema>
{
Title = "News",
LayoutBindings = (viewModel, item) =>
{
viewModel.Title = item.Title.ToSafeString();
viewModel.SubTitle = item.Summary.ToSafeString();
viewModel.Description = item.Summary.ToSafeString();
viewModel.Image = item.ImageUrl.ToSafeString();
},
NavigationInfo = (item) =>
{
return null;
}
};
}
}
public override DetailPageConfig<RssSchema> DetailPage
{
get
{
var bindings = new List<Action<ItemViewModel, RssSchema>>();
var actions = new List<ActionConfig<RssSchema>>
{
};
return new DetailPageConfig<RssSchema>
{
Title = "News",
LayoutBindings = bindings,
Actions = actions
};
}
}
public override string PageTitle
{
get { return "News"; }
}
}
}
Update 2: here is the XAML from the List page
<Page
x:Class="MyWindows10App.Views.NewsListPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:was_actions="using:AppStudio.Uwp.Actions"
xmlns:was_commands="using:AppStudio.Uwp.Commands"
xmlns:was_controls="using:AppStudio.Uwp.Controls"
xmlns:layouts="using:MyWindows10App.Layouts"
xmlns:list_layouts="using:MyWindows10App.Layouts.List"
xmlns:controls="using:MyWindows10App.Layouts.Controls"
xmlns:vm="using:MyWindows10App.ViewModels"
xmlns:triggers="using:MyWindows10App.Triggers"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DataContext="{d:DesignData Source=/Assets/Design/DesignData.json, Type=vm:DesignViewModel, IsDesignTimeCreatable=true}"
mc:Ignorable="d">
<Grid Background="{StaticResource AppBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="15"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.ColumnSpan="2" Background="{StaticResource AppBarBackground}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="48"/>
<TextBlock Grid.Row="0" Grid.Column="0" Margin="{Binding ViewModel.PageTitleMargin}" Text="{Binding ViewModel.PageTitle}" Foreground="{StaticResource AppBarForeground}" FontSize="21" VerticalAlignment="Center" HorizontalAlignment="Left" TextTrimming="WordEllipsis" MaxLines="1"/>
<was_actions:ActionsCommandBar
x:Name="appBar"
ActionsSource="{Binding ViewModel.Actions}" Style="{StaticResource WasCommandBarStyle}"
Foreground="{StaticResource AppBarForeground}"
IsVisible="{Binding ViewModel.HasActions}"
Background="{StaticResource AppBarBackground}"
Grid.Row="{Binding ViewModel.AppBarRow}"
Grid.Column="{Binding ViewModel.AppBarColumn}"
Grid.ColumnSpan="{Binding ViewModel.AppBarColumnSpan}">
</was_actions:ActionsCommandBar>
<ProgressBar Grid.Row="1" Grid.ColumnSpan="2" Height="3" Margin="0,6,0,6" IsIndeterminate="True" Foreground="{StaticResource PageTitleForeground}" Visibility="{Binding ViewModel.IsBusy, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Collapsed}"/>
<was_controls:ErrorNotificationControl Grid.ColumnSpan="2" x:Uid="ListErrorNotificationControl" Grid.Row="2" ErrorVisibility="{Binding ViewModel.HasLoadDataErrors, Converter={StaticResource BoolToVisibilityConverter}}" ErrorColor="{StaticResource PageTitleForeground}" Margin="10,0,18,0"/>
<list_layouts:ListBigHorizontalCardBox Grid.Row="3" Grid.ColumnSpan="2" DataContext="{Binding ViewModel}" ItemsSource="{Binding Items}" ItemClickCommand="{Binding ItemClickCommand}" OneRowModeEnabled="False" Margin="19,0,12,0" />
<controls:DataUpdateInformationControl Grid.ColumnSpan="2" Grid.Row="4" LastUpdateDateTime="{Binding ViewModel.LastUpdated}" Color="{StaticResource PageTitleForeground}" Margin="8,4,8,4" HorizontalAlignment="Left" HasLocalData="{Binding ViewModel.HasLocalData}"/>
</Grid>
</Page>
In UWP apps, While performing navigating you can use URI scheme or recommend any app to use that URI to open with.
You can use the http URI scheme to launch default web browser as follows
// The URI to launch
var uriFeed = new Uri(#"http://www.myblogfeed.com");
// Launch the URI
var success = await Windows.System.Launcher.LaunchUriAsync(uriFeed);
when launching any URI, you can also pass in LaucherOptions obect, where you can specify the preferredApplication for URI to launch it. Here is the example from a msdn page.
// Set the recommended app
var options = new Windows.System.LauncherOptions();
options.PreferredApplicationPackageFamilyName = "Contoso.URIApp_8wknc82po1e";
options.PreferredApplicationDisplayName = "Contoso URI Ap";
// Launch the URI and pass in the recommended app
// in case the user has no apps installed to handle the URI
var success = await Windows.System.Launcher.LaunchUriAsync(uriContoso, options);
Related
I am working on an interactive app that shows different video's based on different stages, I am using C# and WPF and I am trying to use a MediaElement and change it source but it only let me play 1 video file and will not change to the next video, it will keep playing the same file over and over again, I just can't seem to understand why is this happening, I also couldn't find a solution to this online, I have embedded both video files "Stage8.mp4" and "Stage12.mp4" in my solution explorer, Both video files are set to copy if newer and content, also I don't think there is something wrong in the path because if I switch between them it will play the correct file, it just won't change the source in real time.
here are my codes:
C#:
using System;
using System.Windows;
namespace WPF_Tester
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
string NameChecker;
byte stage = 0;
private void BTN1_Click(object sender, RoutedEventArgs e)
{
NameChecker = "Name: " + TXT1.Text + " Last: " + TXT2.Text;
if (testlistview.Items.Contains(NameChecker))
{
MessageBox.Show("The name already exists.");
}
else
{
testlistview.Items.Add(NameChecker);
}
if (stage == 0)
{
TestElement.Source = new Uri("Stage12.mp4", UriKind.Relative);
TestElement.Play();
stage = 1;
}
if (stage == 1)
{
TestElement.Source = new Uri("Stage8.mp4", UriKind.Relative);
TestElement.Play();
stage = 0;
}
}
}
}
XAML:
<Window x:Class="WPF_Tester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Tester"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" FontSize="20" Margin="20,40,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"></TextBlock>
<TextBox x:Name="TXT1" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="18" Margin="80,40,0,0" MinWidth="30"></TextBox>
<TextBlock Text="Last Name:" Grid.Column="0" Grid.Row="0" FontSize="20" Margin="20,80,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"></TextBlock>
<TextBox x:Name="TXT2" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="18" Margin="120,80,0,0" MinWidth="30"></TextBox>
<Button x:Name="BTN1" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Add Name" FontSize="20" Margin="20,180,0,0" Click="BTN1_Click"></Button>
<!-- here we set controls for the second column.-->
<ListView x:Name="testlistview" Grid.Column="1" Margin="20,40,20,20" FontSize="20" ></ListView>
<MediaElement Name="TestElement" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,200,20,0" UnloadedBehavior="Manual" Source="/Stage12.mp4" LoadedBehavior="Play"></MediaElement>
</Grid>
Thanks in advance and have a great day!
There is an else missing. Your second if statement always resets the file to the first. Adding else should implement the desired toggling.
if (stage == 0)
{
TestElement.Source = new Uri("Stage12.mp4", UriKind.Relative);
TestElement.Play();
stage = 1;
}
//we need an else here, otherwise source is always "Stage12.mp4
else if (stage == 1)
{
TestElement.Source = new Uri("Stage8.mp4", UriKind.Relative);
TestElement.Play();
stage = 0;
}
[enter image description here][1]I want to make an application that shows all files in a folder as buttons, so I can open them from the application. So they are getting added dynamically. But I have a problem: I need to show them like a grid, side by side. And if there are more than 9 files it needs to scroll down. I have tried with the layout:
<Grid Name="buttonGrid">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Grid Height="450" Width="800" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
</Grid>
</ScrollViewer>
</Grid>
And I C#:
public partial class PlayGame : Page
{
public PlayGame()
{
InitializeComponent();
AddButtons();
}
//Add buttons to grid
private void AddButtons()
{
var folderName = $"{AppDomain.CurrentDomain.BaseDirectory}games";
if (!Directory.Exists(folderName))
{
Directory.CreateDirectory(folderName);
}
var allFiles = Directory.GetFiles(folderName);
foreach (string fileName in allFiles)
{
var fi = new FileInfo(fileName);
Button newBtn = new Button
{
Content = fi.Name,
Name = "Button" + fi.Name.Replace(".", "_"),
BorderThickness = new Thickness(0)
};
Grid.SetRow(newBtn, 0);
Grid.SetColumn(newBtn, 0);
newBtn.Click += OpenFile;
buttonGrid.Children.Add(newBtn);
}
}
}
And it works partly... The buttons are getting added, and they work, but they are stacked on each other. So how would i fix that?
I want it like this: https://i.stack.imgur.com/6EUKS.png
But dynamically for each file, there is in a folder. And if there are more than 9 files extend downwards so the scrollviewer comes into action.
Try using
<ScrollViewer Height="300">
<WrapPanel Name="listView" Orientation="Horizontal">
</WrapPanel>
</ScrollViewer>
Your very close.
Try increasing the column
Grid.SetColumn(newBtn, i);
for every iteration.
Then you can also set the row
Grid.SetRow(newBtn, i % 3);
to add a new row every three buttons.
Now if you want a new row you can add it with this command:
buttonGrid.RowDefinitions.Add(new RowDefinition());
I have a problem where im trying to use a Telerik Jump List with DataVirtualizationMode.Automatic, but i can't get it to work. The reason why i want to use this, is because i want my app to only download the data(games) which is in the current view of the Jump List control and not the whole data everytime. For example if i have searched for "Batman", and its returning 50 games, i don't want it to download and load all the games, only those i can see in the Jump List control.
Here is a sample of using DataVirtualizationMode.Automatic from Telerik, but i couldn't get it to work with my app: http://www.telerik.com/help/windows-phone/raddataboundlistbox-features-datavirtualization-automatic.html
Below is my Jump List control which i want to use with data virtualization.
MainPage.xaml:
<phone:PivotItem Header="Browse">
<Grid>
<telerikPrimitives:RadTextBox Name="txtSearch" HorizontalAlignment="Left" VerticalAlignment="Top" Height="80" Width="390"/>
<telerikPrimitives:RadImageButton Name="imgBtnSeachGame" VerticalAlignment="Top" HorizontalAlignment="Right" ButtonShape="Ellipse" BorderThickness="2" Margin="0,8,0,0" Click="imgBtnSeachGame_Click"></telerikPrimitives:RadImageButton>
<Controls:RadJumpList Name="jlGameList" ItemsSource="{Binding}" Tap="jlGameList_Tap" Margin="0,90,0,0" DataVirtualizationMode="Automatic">
<Controls:RadJumpList.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="{StaticResource PhoneAccentBrush}"
Padding="{StaticResource PhoneTouchTargetOverhang}"
Margin="0,0,0,0">
<TextBlock Name="tblGameTitle" Style="{StaticResource PhoneTextGroupHeaderStyle}" ManipulationStarted="tblGameTitle_ManipulationStarted" ManipulationCompleted="tblGameTitle_ManipulationCompleted">
<Run Text="{Binding GameTitle}"></Run>
</TextBlock>
</Border>
<Grid Background="#242424" Grid.Row="1">
<Image Name="imgGameList" Margin="0,0,0,0" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top" Height="96" Width="96">
<Image.Source>
<BitmapImage UriSource="{Binding BoxArtFrontThumb}"
CreateOptions="BackgroundCreation" DecodePixelHeight="96" DecodePixelWidth="96" />
</Image.Source>
</Image>
<TextBlock Margin="110,0,0,0" Text="Platform" FontWeight="Bold" TextWrapping="Wrap" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtPlatform" Margin="110,20,0,0" Text="{Binding Platform}"></TextBlock>
<TextBlock Text="Release Date" FontWeight="Bold" Margin="110,46,0,0" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtReleaseDate" Margin="110,66,0,0" Text="{Binding ReleaseDate}"></TextBlock>
<!--</StackPanel>-->
</Grid>
<Grid Grid.Row="2"></Grid>
</Grid>
</DataTemplate>
</Controls:RadJumpList.ItemTemplate>
</Controls:RadJumpList>
</Grid>
</phone:PivotItem>
Below is where i bind my DataContext to my GetGamesListItems ObservableCollection in my GameData class. The imgBtnSearchGame_Click event method is being called when a user have typed for example "Batman" in my textbox txtSearch and tapped the button, it will then send the text to my GetGamesListData method.
MainPage.cs:
GameData gd = new GameData();
public MainPage()
{
InitializeComponent();
jlGameList.DataContext = gd.GetGamesListItems;
}
private void imgBtnSeachGame_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
gd.GetGamesListData(txtSearch.Text, "", "");
}
}
Below is where i download the data in XML for the game name searched for. For example if it is "Batman" it will find and return all games with "Batman". The "BoxArtFrontThumb" Property is where im storing all the images for each game and is using async, because sometimes there can be quite alot of images it has to download and show.
GameData.cs
public void GetGamesListData(string name, string platform, string genre)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += GetGamesListRequestCompleted;
webClient.DownloadStringAsync(new Uri("http://thegamesdb.net/api/GetGamesList.php?name=" + name));
}
private async void GetGamesListRequestCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
GetGamesListItems.Clear();
var feedXml = XDocument.Parse(e.Result);
var gameDataTasks = feedXml.Root.Descendants("Game").Select(
async x => new GetGamesList
{
ID = (int)x.Element("id"),
GameTitle = (string)x.Element("GameTitle"),
ReleaseDate = (string)x.Element("ReleaseDate") ?? "N/A",
Platform = (string)x.Element("Platform") ?? "N/A",
BoxArtFrontThumb = new Uri(await GetBoxArtFrontThumbAsync((int)x.Element("id")), UriKind.RelativeOrAbsolute),
}).ToList();
var gameData = await Task.WhenAll(gameDataTasks);
foreach (var item in gameData)
{
GetGamesListItems.Add(item);
}
}
}
Below is where its finding and storing the images for the games.
public async Task<string> GetBoxArtFrontThumbAsync(int id)
{
var client = new HttpClient();
var result = await client.GetStringAsync("http://thegamesdb.net/api/GetArt.php?id=" + id);
var feedXml = XDocument.Parse(result);
var gameData = feedXml.Root.Descendants("Images").Select(x => new GetArt
{
BoxArtFrontThumb = new Uri(GetBoxArtFrontThumb(x), UriKind.RelativeOrAbsolute),
}).ToList();
return gameData.Single().BoxArtFrontThumb.ToString();
}
private static string GetBoxArtFrontThumb(XElement gameNode)
{
string data = "http://thegamesdb.net/banners/" + (string)gameNode.Descendants("boxart")
.FirstOrDefault(b => (string)b.Attribute("side") == "front");
if (data == "http://thegamesdb.net/banners/")
{
data = "/NoImage.jpg";
}
return data;
}
I really hope i explained this well enough and hope that there is someone that can help me solve this problem. Thanks.
Although you are using JumpList, the mechanism for Virtualizing the data is the same as the DataBoundListBox. (You can find more information here in the DataBoundListBox docs. There is a good tutorial using an OData service.)
In order for the Automatic mode to work properly, you need to be using Telerik's VirtualizingDataCollection object and initialize it with the proper arguments (count and page size).
I don't see this in the code you have provided above, can you please open a support ticket so that I can investigate further? See my comment above for the link. Let me know the ticket number and I'll provide further assistance.
I have Json links and i need to get the data into listview. listview consists of picture, Itemname and Price. I m using Newtonsoft.Json. I need to pass headers(username, password,..) and then call the menuitem link into my application to access the menuitem data. I have many items in this listview to display. I am giving only one example below for Json data. Pls suggest me any good information as i am new to json. Thank you.
{"data":[{"Menuitemid":1,"Menucategoryid":1,"Itemname":"Hot And Spicy Chicken Wings","Description":"About Hot And Spicy Chicken Wings","Price":12.0,"Picture":"http://www.ownboughtearned.com/demo/wp-content/uploads/2012/11/small_thumbnail.png","Thumbnail":null,"Active":true}]}
/
/Listbox binding in xaml
<ListBox x:Name="lstItems" SelectionChanged="lstItems_SelectionChanged" CharacterSpacing="-1" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1.2" BorderBrush="Silver"
HorizontalAlignment="Stretch" MinWidth="440">
<Grid Margin="0 10 0 10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!--<RowDefinition Height="*" />-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="105" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="70" />
<!--<ColumnDefinition Width="*" />-->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<Border BorderBrush="Silver" CornerRadius="3" Height="97"
Width="97" Background="White">
<Image Source="{Binding Path=Picture}" Stretch="Fill"
Height="95" Width="95" />
</Border>
</StackPanel>
<TextBlock Text="{Binding Path=Itemname}" MaxWidth="290" Margin="13 0 0 0"
FontSize="25" Foreground="#5b261e" TextWrapping="Wrap" TextTrimming="None"
Grid.Column="1" Grid.Row="0">
</TextBlock>
<TextBlock Margin="5" Text="{Binding Path=Price}"
FontSize="20" Foreground="#5b261e" Grid.Column="2" Grid.Row="1" VerticalAlignment="Center" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
//MenuRepository.cs
namespace MenuInfo.Concrete
{
public class MenuRepository : IMenuRepository
{
public List<MenuItem> listitems = new List<MenuItem>();
public List<MenuItem> ListMenus()
{
System.Uri targetUri = new System.Uri("http://xxxxxxxxxx.testshell.net/api/restaurant/menuitems/1");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(targetUri);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers["username"] = "info#xxxxxxxxxx.com";
httpWebRequest.Headers["password"] = "xxxxxxxxxxxxxxxxxxxxxxxx";
httpWebRequest.BeginGetResponse(OnGetResponseCompleted, httpWebRequest);
return listitems;
}
private async void OnGetResponseCompleted(IAsyncResult ar)
{
try
{
var httpWebRequest = (HttpWebRequest)ar.AsyncState;
var response = httpWebRequest.EndGetResponse(ar);
var jsonSerializer = new DataContractJsonSerializer(typeof(MenuItemObject));
var responseObject = (MenuItemObject)jsonSerializer.ReadObject(response.GetResponseStream());
foreach (MenuItem loc in responseObject.data)
{
listitems.Add(loc);
}
}
catch (Exception ex)
{
}
}
}
}
Your problem stems from the fact that you are returning an empty collection from the ListMenus method. The method will return before it has a chance to populate the collection within the OnGetResponseCompleted callback. You can get around this in one of two ways. The first is to change you listitems variable to be an ObservableCollection.
public ICollection<MenuItem> listitems = new ObservableCollection<MenuItem>();
With this approach you will continue to return an empty collection, but when you add items to it within the OnGetResponseCompleted method, it will notify the ListBox that an item was added (provided that you set the ITemsSource to be the result of the ListMenus method. Doing it this way has negative performance impacts. For each item that you add, it notifies the UI to update rather than one big update with all of the items. It is also likely that it will throw an exception that you are trying to update a UI component when not on the UI thread. The callback OnGetResponseCompleted will likely be on a separate thread.
Another, and better approach would be to return the results using the async/await pattern. You could use the new HttpClient class to do this, but if you like using a WebRequest, you can still accomplish this using a TaskCompletionSource.
public Task<IList<MenuItem>> ListMenus()
{
var completion = new TaskCompletionSource<IList<MenuItem>>();
System.Uri targetUri = new System.Uri("http://xxxxxxxxxx.testshell.net/api/restaurant/menuitems/1");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(targetUri);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers["username"] = "info#xxxxxxxxxx.com";
httpWebRequest.Headers["password"] = "xxxxxxxxxxxxxxxxxxxxxxxx";
httpWebRequest.BeginGetResponse(ar =>
{
try
{
using (var response = httpWebRequest.EndGetResponse(ar))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
var responseObject =
Newtonsoft.Json.JsonConvert.DeserializeObject<MenuItemObject>(reader.ReadToEnd());
foreach (MenuItem loc in responseObject.data)
{
listitems.Add(loc);
}
}
}
}
catch (Exception ex)
{
}
completion.SetResult(listitems);
}, null);
return completion.Task;
}
With this approach, you would await the result of the ListMenus and set the ItemsSource from it.
lstItems.ItemsSource = await ListMenus();
Now you get the results populated, and do not have the performance impact of adding items one at a time.
I want to create a game, where the word is given, but there's one letter missing and you need to choose from one of the letters given below. Being a beginner with C#, I find very difficult to make this work. Right now, I have a word class, which has WordFull, LetterA, LetterB, LetterC, index (where I need to put the letter in) and a CorrectLetter. Then, I load this word object, where I put letter one by one in textboxes and if letter's index in the word (h[e]llo = 1) is equal to the current letter's index property (index = 1), then it displays blank underlined textbox. When you click on that letter, then it checks whether that letter is correct with CorrectLetter property and that's the place where I'm stuck. I want to put that letter in place of empty textbox. But how do I choose it? I think I'm doing something wrong.
TL;DR
I want to make a letter game and I need an advice how to do it.
My XAML grid:
<TabItem Name="zaisti" Header="Vykdyti" IsSelected="True">
<Grid Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" Grid.Column="0">
<StackPanel Name="letters" Orientation="Horizontal">
</StackPanel>
</Viewbox>
<Image Grid.Row="0" Grid.Column="1" Name="img" Margin="10" Source="pack://siteoforigin:,,,/pic.jpg"/>
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Button.Click="Grid_Click">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Margin="10">
<Button.Content>
<Viewbox>
<Label Name="Option1" Content="{Binding LetterA}"></Label>
</Viewbox>
</Button.Content>
</Button>
<Button Grid.Column="1" Margin="10">
<Button.Content>
<Viewbox>
<Label Name="Option2" Content="{Binding LetterB}"></Label>
</Viewbox>
</Button.Content>
</Button>
<Button Grid.Column="2" Margin="10">
<Button.Content>
<Viewbox>
<Label Name="Option3" Content="{Binding LetterC}"></Label>
</Viewbox>
</Button.Content>
</Button>
</Grid>
Code behind:
public partial class MainWindow : Window
{
List<Word> Words = new List<Word>()
{
... data ...
};
int index = 0;
public MainWindow()
{
InitializeComponent();
pradzia.IsSelected = true;
zaisti.IsEnabled = false;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
zaisti.IsSelected = true;
zaisti.IsEnabled = true;
letters.Children.Clear();
LoadWord(index);
this.DataContext = Words[index];
}
private void Grid_Click(object sender, RoutedEventArgs e)
{
if (index == Words.Count() - 1) return;
MessageBox.Show((((e.Source as Button).Content as Viewbox).Child as Label).Content.ToString());
if ((((e.Source as Button).Content as Viewbox).Child as Label).Content.ToString() == Words[index].LetterCorrect)
{
letters.Children.Clear();
LoadWord(++index);
this.DataContext = Words[index];
}
}
private void LoadWord(int i)
{
int a = 0;
foreach (char l in Words[i].WordFull)
{
TextBlock letter = new TextBlock();
letter.Foreground = new SolidColorBrush(Colors.Gray);
letter.Text = l.ToString();
letter.Margin = new Thickness(2);
if (Words[i].index == a)
{
letter.Text = ((char)160).ToString() + ((char)160).ToString();
// Create an underline text decoration. Default is underline.
TextDecoration myUnderline = new TextDecoration();
// Create a solid color brush pen for the text decoration.
myUnderline.Pen = new Pen(Brushes.Red, 1);
myUnderline.PenThicknessUnit = TextDecorationUnit.FontRecommended;
// Set the underline decoration to a TextDecorationCollection and add it to the text block.
TextDecorationCollection myCollection = new TextDecorationCollection();
myCollection.Add(myUnderline);
letter.TextDecorations = myCollection;
}
a++;
letters.Children.Add(letter);
}
}
}
Word class:
class Word
{
public string WordFull { get; set; }
public string LetterA { get; set; }
public string LetterB { get; set; }
public string LetterC { get; set; }
public string LetterCorrect { get; set; }
public int index { get; set; }
}
Based on what I'm seeing, I would do the following
move the creation of the individual letter elements (including the underline) into their own methods that return the component to display.
Then when the player picks the correct letter,
find the underline element,
remove it from the letters visual control,
and replace it with the the correct letter element.
edit - based on comment
There are several ways of getting to the elements in the Children collection. If you know the actual element,
letters.Children.Remove(element);
will allow you to remove the specified element, or
letters.Children[index];
will work if you know the index.