Help with Silverlight and SharePoint
-
16-10-2019 - |
Question
As a continuation of my last question, I can get the data correctly now just I am having a problem getting it to display. I want it to be in a DataForm control but I seem to be unable to connect it correctly. here is my code:
namespace SP2010
{
public partial class MainPage : UserControl
{
ClientContext context;
Web spWeb;
List customerList;
ListItemCollection allCustomers;
public MainPage()
{
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
InitializeComponent();
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this;
context = new ClientContext(ApplicationContext.Current.Url);
spWeb = context.Web;
context.Load(spWeb);
customerList = spWeb.Lists.GetByTitle("testlist");
context.Load(customerList);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View>
<Query></Query>
<RowLimit>1000</RowLimit>
</View>";
allCustomers = customerList.GetItems(camlQuery);
context.Load(allCustomers);
context.ExecuteQueryAsync(new ClientRequestSucceededEventHandler(OnRequestSucceeded), new ClientRequestFailedEventHandler(OnRequestFailed));
}
private void OnRequestSucceeded(Object sender, ClientRequestSucceededEventArgs args)
{
Dispatcher.BeginInvoke(DisplayListData);
}
private void OnRequestFailed(Object sender, ClientRequestFailedEventArgs args)
{
MessageBox.Show(args.ErrorDetails + " " + args.Message);
}
public ObservableCollection<SPCustomers> Printers
{
get
{
if (printers == null)
{
printers = new ObservableCollection<SPCustomers>();
foreach (ListItem item in allCustomers)
{
printers.Add(new SPCustomers
{
IPAddress = item["Title"].ToString(),
Make = item["make"].ToString(),
Model = item["model"].ToString(),
xCord = item["x"].ToString(),
yCord = item["y"].ToString()
});
}
}
return (printers);
}
}
private ObservableCollection<SPCustomers> printers;
does anyone know what I am doing wrong?
Solution
Sorry - real old post.. I kind of stumbled upon it...
- In your
MainPage_Loaded
-Method you set theDataContext
. Ater that your UI will bind toPrinters
. - This will cause the
Printers_get
to be executed - which in turn will iterate overallCustomers
.allCustomers
is eithernull
or empty becausecontext.ExecuteQueryAsync(...)
will most definitively not have run at this point. - Then - some time later - you call
context.ExecuteQueryAsync(...)
which fillsallCustomers
- but you never tell your UI that it is time to refresh the Printes...
Real quick (but IMHO the wrong way) would be to move your this.DataContext = this
into OnRequestSucceeded
.
I would:
- make MainPage implement
INotifyPropertyChanged
- in
OnRequestSucceeded
raise thePropertyChanged
-event withPrinters
as the argument and by doing so tell the UI that it is time to update thePrinters
binding. - this will refresh the binding and re-execute
Printers_get
- which will do nothing new, becauseprinters
is no longernull
- so I'd do something about that, too...
To stay close to your code a working example ("probably working" - I have not tested it..) would most probably look like this:
namespace SP2010
{
public partial class MainPage : UserControl
{
ClientContext context;
Web spWeb;
List customerList;
ListItemCollection allCustomers;
public MainPage()
{
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
InitializeComponent();
this.Printers = new ObservableCollection<SPCustomers> ();
this.DataContext = this;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
context = new ClientContext(ApplicationContext.Current.Url);
spWeb = context.Web;
context.Load(spWeb);
customerList = spWeb.Lists.GetByTitle("testlist");
context.Load(customerList);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
@"<View>
<Query></Query>
<RowLimit>1000</RowLimit>
</View>";
allCustomers = customerList.GetItems(camlQuery);
context.Load(allCustomers);
context.ExecuteQueryAsync(new ClientRequestSucceededEventHandler(OnRequestSucceeded), new ClientRequestFailedEventHandler(OnRequestFailed));
}
private void OnRequestSucceeded(Object sender, ClientRequestSucceededEventArgs args)
{
//Dispatcher.BeginInvoke(DisplayListData);
// Fill Printers:
foreach (ListItem item in allCustomers)
{
Printers.Add(new SPCustomers
{
IPAddress = item["Title"].ToString(),
Make = item["make"].ToString(),
Model = item["model"].ToString(),
xCord = item["x"].ToString(),
yCord = item["y"].ToString()
});
}
}
private void OnRequestFailed(Object sender, ClientRequestFailedEventArgs args)
{
MessageBox.Show(args.ErrorDetails + " " + args.Message);
}
public ObservableCollection<SPCustomers> Printers
{
get; private set;
}
Notice that this still doesn't implement INotifyPropertyChanged
, but Printers
gets initialized in the contstructor and before setting the DataContext. This way the Binding to Printers will be o.k. and as you already utilized an ObservableCollection
all changes to the collection will trigger an update of the UI.
Then I am filling the Printers
collection in OnRequestSucceeded (without creating a new ObservableCollection). This way you should be able to see the printers as expected.