I have a MasterDetail UI set up. On the left is a ListView. The ListView is set up like this
public class MasterPageList
{
public string Text { get; set; }
public string Url { get; set; }
public override string ToString()
{
return Text;
}
}
var listOptions = new List<MasterPageList>
{
new MasterPageList{ Text = "Packt website", Url = "http://www.packt.com" },
new MasterPageList{ Text = "Farmtrack Live", Url = "http://www.farmapps.co.uk" },
new MasterPageList{ Text = "Henry Crunn", Url = "" }
};
// create the ListView - this is explained later in the book more fully in the What A Bind chapter
var listView = new ListView
{
ItemsSource = listOptions.ToArray()
};
// create the master page
Master = new ContentPage
{
Title = "Webviewer",
Content = new StackLayout
{
Children =
{
header, listView
}
}
};
The ItemSelected event fires off the recipient pages
void LaunchPage(object s, SelectedItemChangedEventArgs e)
{
var binding = e.SelectedItem as MasterPageList;
var displayPage = new Page();
if (string.IsNullOrEmpty(binding.Url))
{
displayPage = (Page)Activator.CreateInstance(typeof(WebviewGenerated));
}
else
{
displayPage.BindingContext = e.SelectedItem;
displayPage = (Page)Activator.CreateInstance(typeof(Webview));
}
Detail = new NavigationPage(displayPage);
IsPresented = false;
}
When either of the first two ListItems are selected, the receiving ContentPage is instantiated, but the BindingContext of the page is null. I've tried a number of other methods to obtain the URL from the sending page.
From what I can see from other examples, what I am doing is correct, but the results show otherwise.
Is there something else I need to be doing to pass the URL through to the web view page?
try the following:
var params = new Params {
url = "https://www.google.com",
querystring = ""
};
var secondPage = new SecondPage ();
secondPage.BindingContext = params;
await Navigation.PushAsync (secondPage);
Related
I am new to programming for winrt. I am using VS 2015, trying to do some testing on ObservableCollection to see how the change in the collection got reflected on the UI. I must have done something incorrectly. Just do not know what.
This is my model:
class MyItems
{
public int ItemID { get; set; }
public string ItemDescription { get; set; }
}
class MyItemList:List<MyItems>
{
public MyItemList()
{
Random r = new Random(DateTime.Now.Day);
for (int i = 0; i < r.Next(10)+1; i++)
{
this.Add(new MyItems() { ItemID = i + 1,
ItemDescription = string.Format("Item_{0}", i + 1) });
}
}
public ObservableCollection<MyItems> getEven()
{
return new ObservableCollection<MyItems>(this.Where(x=>x.ItemID%2==0).ToList());
}
public void AddMoreItems(int v)
{
int total = this.Count;
for (int i = 0 ; i < v; i++)
{
this.Add(new MyItems() { ItemID = total + i, ItemDescription = string.Format("Item_{0}", total+i) });
}
}
}
On MainPage.xaml, I have a button to add items to the list. I have created a listview programmatically and binding to the dataset two ways.
public sealed partial class MainPage : Page
{
static MyItemList myItems = new MyItemList();
public MainPage()
{
this.InitializeComponent();
var t = myItems.getEven();
ListView myListView = new ListView() { ItemTemplate = (DataTemplate)Resources["myItemTemplate"] };
myListView.DataContext = t;
var binding = new Binding();
binding.Source = t;
binding.Mode = BindingMode.TwoWay;
myListView.SetBinding(ListView.ItemsSourceProperty, binding);
MyGrid.Children.Add(myListView);
}
private void AddItems_Click(object sender, RoutedEventArgs e)
{
myItems.AddMoreItems(3);
}
}
When I clicked on the button, 3 more items are added but they are not reflected in my listview. Something else needs to be done beside using the ObservableCollection and set binding to twoWays?
Your problem, essentially, is here:
public ObservableCollection<MyItems> getEven()
{
return new ObservableCollection<MyItems>(this.Where(x=>x.ItemID%2==0).ToList());
}
When you query this and call ToList(), you are creating a new list that is independent of the original. If you add items to the original, it's not going to be reflected in your derived list. Think of it this way:
public ObservableCollection<MyItems> getEven()
{
var filteredList = this.Where(x=>x.ItemID%2==0).ToList()
return new ObservableCollection<MyItems>(filteredList);
}
Adding to this is not going to change the contents filteredList at all.
Additionally, creating a new ObservableCollection every time you access getEven instead of modifying an existing one means that the events when adding and deleting to the observable collection will never fire.
You are using observable collections in a fundamentally incorrect way. Why not just have MyItemList derive from ObservableCollection<T> instead of List<T>?
Collection that inherits from ObservableCollection - What are the benefits?
Also, if you're trying to filter by even/odd, you should look into ICollectionView
WPF Binding filtered ObservableCollection ICollectionView to Combobox
I have a Place data_object in the service side which contains a navigation property Roads:
public class Place : EntityData
{
...
public List<Road> Roads { get; set; }
}
And now on the client side, I want to get a Place object using its id, but the navigation property Roads just won't load. Is there any parameter or attribute I can add to make it work?
My code for it:
var roadList = await App.MobileService.GetTable<Place>()
.LookupAsync(placeId);
Since loading navigation properties in EF requires a JOIN operation in the database (which is expensive), by default they are not loaded, as you noticed. If you want them to be loaded, you need to request that from the client, by sending the $expand=<propertyName> query string parameter.
There are two ways of implementing this: in the server and in the client. If you want to do that in the server, you can implement an action filter which will modify the client request and add that query string parameter. You can do that by using the filter below:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
class ExpandPropertyAttribute : ActionFilterAttribute
{
string propertyName;
public ExpandPropertyAttribute(string propertyName)
{
this.propertyName = propertyName;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
var uriBuilder = new UriBuilder(actionContext.Request.RequestUri);
var queryParams = uriBuilder.Query.TrimStart('?').Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries).ToList();
int expandIndex = -1;
for (var i = 0; i < queryParams.Count; i++)
{
if (queryParams[i].StartsWith("$expand", StringComparison.Ordinal))
{
expandIndex = i;
break;
}
}
if (expandIndex < 0)
{
queryParams.Add("$expand=" + this.propertyName);
}
else
{
queryParams[expandIndex] = queryParams[expandIndex] + "," + propertyName;
}
uriBuilder.Query = string.Join("&", queryParams);
actionContext.Request.RequestUri = uriBuilder.Uri;
}
}
And then you can decorate your method with that attribute:
[ExpandProperty("Roads")]
public SingleItem<Place> GetPlace(string id) {
return base.Lookup(id);
}
Another way to implement this is to change the client-side code to send that header. Currently the overload of LookupAsync (and all other CRUD operations) that takes additional query string parameters cannot be used to add the $expand parameter (or any other $-* parameter), so you need to use a handler for that. For example, this is one such a handler:
class MyExpandPropertyHandler : DelegatingHandler
{
string tableName
string propertyName;
public MyExpandPropertyHandler(string tableName, string propertyName)
{
this.tableName = tableName;
this.propertyName = propertyName;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Method.Method == HttpMethod.Get.Method &&
request.RequestUri.PathAndQuery.StartsWith("/tables/" + tableName, StringComparison.OrdinalIgnoreCase))
{
UriBuilder builder = new UriBuilder(request.RequestUri);
string query = builder.Query;
if (!query.Contains("$expand"))
{
if (string.IsNullOrEmpty(query))
{
query = "";
}
else
{
query = query + "&";
}
query = query + "$expand=" + propertyName;
builder.Query = query.TrimStart('?');
request.RequestUri = builder.Uri;
}
}
return await base.SendAsync(request, cancellationToken);
return result;
}
}
And you'd use the handler by creating a new instance of MobileServiceClient:
var expandedClient = new MobileServiceClient(
App.MobileService.ApplicationUrl,
App.MobileService.ApplicationKey,
new MyExpandPropertyHandler("Place", "Roads"));
var roadList = await App.MobileService.GetTable<Place>()
.LookupAsync(placeId);
I have a class like this,
public class Item
{
private string _itemCode=string.empty;
private string _itemName = string.empty;
//Dynamic variable to keep custom properties
private dynamic _customProperties = new ExpandoObject();
public string ItemCode
{
get{return _itemCode;}
set{_itemCode=value;}
}
public string ItemName
{
get{return _itemName;}
set{_itemName=value;}
}
private ExpandoObject CustomProperties
{ get { return _customProperties; } }
//Method to load objects
publc static List<Item> Load()
{
List<Item> itemList = new List<Item>();
//Create Item objects
Item itm1 = new Item();
{
_itemCode="Code1";
_itemName="Name1";
}
//Create custom properties
itm1._customProperties.Test1 = "t1";
itemList.Add(itm1);
//Add more items as above with the several custom properties
return itemList;
}
}
In my windows form I'm getting a Item list and assigning it to the datasource of the datagridview.
List<Item> lstItems= Item.Load();
//Add item list to the data grid view
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = lstItems;
this.dataGridView1.DataSource = bindingSource;
this.dataGridView1.Refresh();
When form runs, grid doesn't show the custom properties I have added to the Item.CustomProperties. How can I change my code to overcome this.
Try this
Set
bindingSource.DataMember = "Your value"; //
http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx
I am trying to implement a Settings dialog for iOS using MonoTouch and the DialogViewController.
The class below contains some public properties, and a method to get a DialogViewController for it.
The problem is that when the view disappears, the string value in thisName.Value is null (I have of course filled in something in the text field).
Why?
public class Settings
{
public string Name { get; set; }
public int MagicNumber { get; set; }
public bool ThisIsEnabled{ get; set; }
public Settings ()
{
var defaults = NSUserDefaults.StandardUserDefaults;
Name = defaults.StringForKey ("name");
ThisIsEnabled = defaults.BoolForKey("thisisenabled");
MagicNumber = defaults.IntForKey ("123");
}
public UIViewController GetViewController ()
{
var thisBoolean = new BooleanElement ("This boolean", ThisIsEnabled);
var thisName = new EntryElement ("Name", "name", Name);
thisName.KeyboardType = UIKeyboardType.ASCIICapable;
var root = new RootElement ("Options"){
new Section (){thisBoolean,thisName}
};
var dv = new DialogViewController (root, true){Autorotate= true};
dv.ViewDissapearing += delegate {
ThisIsEnabled = thisBoolean.Value; // <== This works
Name = thisName.Value; // <== This is NULL
var defaults = NSUserDefaults.StandardUserDefaults;
defaults.SetBool (ThisIsEnabled, "thisisenabled");
defaults.SetString (Name, "name");
};
return dv;
}
}
}
the current release of MT.D will not "save" a field's value until the user navigates away from it. This may be what you are seeing.
This behavior has been fixed, but has not been released yet.
How do you retrieve the URL for a discussion board item? That is, the URL displayed when you mouse over the subject line (once the list has been added to the page as a web part).
protected global::System.Web.UI.WebControls.GridView gvForum;
public string Region
{
get
{
return "";
}
}
public string DefaultRegion { get; set; }
public int Top { get; set; }
public string ListName
{
get
{
string listName=string.Empty;
if (!string.IsNullOrEmpty(this.Region))
listName=string.Format("{0} {1}","Forum",this.Region);
else
listName = string.Format("{0} {1}", "Forum", this.DefaultRegion);
return listName;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
private void BindGrid()
{
string region = this.Region;
string caml=#"<OrderBy><FieldRef Name=""Modified"" /></OrderBy>";
try
{
using (SPSite spSite = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb spWeb = spSite.OpenWeb())
{
SPQuery spQ = new SPQuery();
spQ.Query = caml;
spQ.RowLimit = (uint)this.Top;
SPList spList = spWeb.Lists[ListName];
SPListItemCollection items = spList.GetItems(spQ);
if (items != null && items.Count > 0)
{
gvForum.DataSource = items;
gvForum.DataBind();
}
else
{
this.Visible = false;
}
}
}
}
catch (Exception ex)
{
Logger.Log(ex.Message, System.Diagnostics.EventLogEntryType.Error);
}
}
protected void gvForum_RowDataBound(object sender, GridViewRowEventArgs e)
{
SPListItem item = e.Row.DataItem as SPListItem;
Label lblTitle = e.Row.FindControl("lblTitle") as Label;
HtmlAnchor aURL = e.Row.FindControl("aURL") as HtmlAnchor;
if (item != null)
{
if (lblTitle != null && aURL != null)
{
aURL.HRef = "~/" + item.Url;
lblTitle.Text = item["Title"].ToString();
}
}
}
protected void gvForum_RowDataBound(object sender, GridViewRowEventArgs e)
{
SPListItem item = e.Row.DataItem as SPListItem;
Label lblTitle = e.Row.FindControl("lblTitle") as Label;
HtmlAnchor aURL = e.Row.FindControl("aURL") as HtmlAnchor;
if (item != null)
{
if (lblTitle != null && aURL != null)
{
aURL.HRef = "~/" + item.Url;
lblTitle.Text = item["Title"].ToString();
}
}
}
You can use use "TopicPageUrl" field column to directly get the discussion topic by using REST api URL
http://sp2013.in/_api/web/Lists/GetByTitle('Discussion')/Items?$select=Title,TopicPageUrl,DiscussionLastUpdated,Folder/ItemCount,LastReplyBy/Title,Author/Title&$expand=Folder,LastReplyBy,Author&$orderby=DiscussionLastUpdated desc
The above code is also useful to get discussion last updated, reply count (its saved in folder), last replied by.
Are you asking how to find the URL for an individual discussion in a discussion board? Or an individual reply to a discussion?
You can give just subject name like http://site/discussion/lists/discussionboard/discusontitlename or subject
You may not have the list item, but if you do just look at the "FileRef" property. It will look like "https://mycompany.sharepoint.com/sites/Lists/discussion/". If I put that URL in the browser (I'm using SharePoint Online), it redirects me to the https://mycompany.sharepoint.com/Lists/Discussion/Flat.aspx?RootFolder=... URL.
To generate the direct url to a particular discussion item, on Client side (using a REST API call), you could try this:
var jqXhr = $.ajax({
url:"/DiscussionSite/_api/lists/getByTitle('Discussions')/items?
$select=ID,FileRef,ContentTypeId,Title,Body&
$filter=ContentType eq 'Discussion'",
headers: { 'Accept': 'application/json;odata=verbose'}
});
// Fetch only the discussions from the Discussion list (excl. Messages)
jqXhr.done(function(data){
// Picking only the first item for testing purpose
// Feel free to loop through the response if necessary
var firstItem = data.d.results[0],
firstItemUrl = '/DiscussionSite/Lists/Discussions/Flat.aspx?RootFolder=' + firstItem.FileRef + '&FolderCTID' + firstItem.ContentTypeId;
// Result - /DiscussionSite/Lists/Discussions/Flat.aspx?RootFolder=/DiscussionSite/Lists/Discussions/My Discussion Topic 1&FolderCTID0x01200200583C2BEAE375884G859D2C5A3D2A8C06
// You can append "&IsDlg=1" to the Url for a popup friendly display of the Discussion Thread in a SharePoint Modal Dialog
console.log(firstItemUrl);
});
Hope this helps!