Populating a ListBox from database - c#

I am using Entity Framework to retrieve records from the database. My user control page crashes every time I run it, but after I comment out the lines in BindLstBox method; my user control page runs well. Is there anything wrong with this code? (DAOActivity is a class file which have CRUD codes in it. I suppose there is nothing wrong there.) It shows this error when i try to run :
'The invocation of the constructor on type 'iStellar.home' that
matches the specified binding constraints threw an exception.' Line
number '5' and line position '14'.
Heres the screenshot of the error :
DAO.DAOActivity daoActivity = new DAO.DAOActivity();
public home()
{
InitializeComponent();
BindListBox();
}
public void BindListBox()
{
listBox1.ItemsSource = daoActivity.GetAll();
listBox1.DisplayMemberPath = "ActivityName";
listBox1.SelectedValuePath = "ActivityID";
}
My XAML :
<ListBox Height="534" HorizontalAlignment="Left" Margin="218,415,0,0"
Name="listBox1" VerticalAlignment="Top" Width="512" />

Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
listBox1.ItemsSource = daoActivity.GetAll();
listBox1.DisplayMemberPath = "ActivityName";
listBox1.SelectedValuePath = "ActivityID";
}));
I hope this will help.

Related

C# .NET Objects doesn't update properties correctly from method being called from derived class

I have derived class in my WPF project like this
public class NetworkCommunicator : WindowWallet
{
System.Windows.Threading.DispatcherTimer listenerTimer = new System.Windows.Threading.DispatcherTimer();
public NetworkCommunicator()
{
listenerTimer.Tick += new EventHandler(listenerTimer_Elapsed);
listenerTimer.Interval = new TimeSpan(0, 0, 1);
listenerTimer.Start();
}
private void listenerTimer_Elapsed(object sender, EventArgs e)
{
base.AddLogContent("some text");
}
}
And the parent class that is also an currently opened window.
public partial class WindowWallet : Window
{
NetworkCommunicator netCommunicator;
public WindowWallet()
{
InitializeComponent();
netCommunicator = new NetworkCommunicator();
}
public virtual void AddLogContent(string s)
{
textBoxNetworkLog.AppendText(Environment.NewLine + s);
}
}
And this is the XAML code of the textBoxNetworkLog
<TextBox x:Name="textBoxNetworkLog" Height="153" Margin="10,0,10.4,33.4" TextWrapping="Wrap" VerticalAlignment="Bottom" VerticalScrollBarVisibility="Auto" AcceptsReturn="True" Text="AnoBIT Network Log started..." IsReadOnly="True" TextChanged="textBoxNetworkLog_TextChanged"/>
The problem is that the textBoxNetworkLog.Text property doesn't update and I can't see the changes in the opened WindowWallet. I made some debugging and I can see that the textBoxNetworkLog.Text is updating every second and the property is changing as expected in the Locals window when I debug my code step by step (every second there is new line of some text as expected). But that's only during the debugging and I see zero changes in the opened WindowWallet.
I know that
The listenerTimer is running
The AddLogContent executes
When I type something in the opened WindowWallet into the textBoxNetworkLog, the textBoxNetworkLog.Text property in the Locals does not (obviously) sync with the text I typed in.
When I try different object other than textBoxNetworkLog in the AddLogContent method, the text doesn't change in the Window aswell
I have only one WindowWallet opened and only one instance of the NetworkCommunicator created
I am doing this on the WPF framework
The textBoxNetworkLog_TextChanged contains literally nothing, so there is no problem there
It just looks like the method doesn't change the text of the textBoxNetworkLog that is in the CURRENT INSTANCE of the opened Window or something like that. Please help me, I am hopeless. Thanks
EDIT: I guess it just doesn't refer to the current instance which I have opened now. I solved it with this one line (maybe there will be more in need in a case there will be more WindowWallet instances opened
WindowWallet CurrentInstanceWallet = Application.Current.Windows.OfType<WindowWallet>().FirstOrDefault();
Solved it by myself. This one line will do the trick.
WindowWallet CurrentInstanceWallet = Application.Current.Windows.OfType<WindowWallet>().FirstOrDefault();
If there are gonna be more instances of WindowWallet's it will maybe need to modify a little bit.

Oxyplot does not display plots in WPF view

I'm working with OxyPlot in WPF. Trying to display PlotModels in a UI.
Sometimes the plot is displayed in the UI and sometimes not.
This code is used to initialize the PlotModel by a BackgroundWorker:
ViewModel:
this.pm = setUpModel();
data2plot();
With the methods:
private PlotModel _pm;
public PlotModel pm
{
get { return _pm; }
set { _pm= value; RaisePropertyChanged("pm"); }
}
private PlotModel setUpModel()
{
PlotModel pm = new PlotModel();
pm.IsLegendVisible = false;
var xAxis= new CategoryAxis();
pm.Axes.Add(xAxis);
var valueAxis = new LinearAxis();
pm.Axes.Add(valueAxis);
return pm ;
}
//tbl holds the data in the second column
private void data2plot(DataTable tbl)
{
var series = new OxyPlot.Series.LineSeries();
int i = 0;
foreach (DataRow row in tbl.Rows)
{
double val = double.Parse(row[1].ToString());
series.Points.Add(new DataPoint(i, val));
i++;
}
this.pm.Series.Add(series);
}
Code used in View to initialize the model:
<Grid HorizontalAlignment="Left" Height="205" Margin="10,117,0,0" VerticalAlignment="Top" Width="308">
<oxypl:PlotView x:Name="plot" Model="{Binding pm,UpdateSourceTrigger=PropertyChanged}" Margin="10" Grid.Row="1">
</oxypl:PlotView>
</Grid>
with the following references
xmlns:oxypl="http://oxyplot.org/wpf"
DataContext="{Binding Source={StaticResource Locator}, Path=ViewModel}"
The Binding works, so I guess there have to be a problem with my PlotModel.
I don't know if this is relevant, but the DataTable tbl is initialized by the Lazy<T> class (with isThreadSafe=true).
When you add to your pm member, the value of pm is not being updated - it's the content of that member that is updated, i.e. the setter is never called, so the RaisePropertyChanged event is never emitted and the view isn't notified of any change. Suggest you build a local set of data and then overwrite pm with a complete set of data at the end, or emit a RaisePropertyChanged event when you're done.
The reason that it is working sometimes I would guess is that the first (and only) time the view reads the content back from the viewmodel you've already populated it, so you see something, but then no updates.
You also have to call
pm.InvalidatePlot(true);
after adding to the series, in order to trigger a redraw.

Set value (int) to checke radio button wpf

Hope you can help me whit this :)
I WANT TO: give the following values to four different radio buttons: 30, 50, 100 and 200 (doesn't really matter what the values is for now). Right now I need to go into the code and change the number my self. I want these radio buttons to do the job when checked.
I will paste the code here. Can you please be very spesific when explaining this to me (if you can and bother to do so).
Thank you!
//Method for establishing connection to database.
// Sette parameter for limit
public static MongoDatabase GetDatabase(string searchText)
{
/* try
{*/
TweetOC.Clear();
MongoServerSettings settings = new MongoServerSettings();
settings.Server = new MongoServerAddress("xxxx", xxxx);
MongoServer server = new MongoServer(settings);
MongoDatabase database = server.GetDatabase("tweet_database");
var collection = database.GetCollection<Tweets>("docs");
System.Console.WriteLine("5");
var query = Query.And(Query.Matches("text", searchText),
Query.NE("geo_enabled", false));
System.Console.WriteLine("6");
//var match = Query.ElemMatch("text", query);
var cursor = collection.Find(query);
cursor.SetLimit(30);
System.Console.WriteLine("7");
//Puts the result from the last query into a list.
var resultList = cursor.ToList();
//Iterates over the previous mentioned list and inserts the content into the ObservableCollcetion created earlier.
foreach (var item in resultList)
TweetOC.Add(item);
System.Console.WriteLine(TweetOC.Count);
return database;
}
I HAVE TO CHANGE CURSOR.LIMIT(manually) ALL THE TIME. I WANT THIS NUMBER TO CHANGE AUTOMATICALLY WHEN A RADIO BUTTON IS CHECKED.
THE METHOD AND XAML WILL FOLLOW:
// I want this to be if radiobutton is 20, then this should be sent to cursor.set limit. I cannot make another string in database.cs without getting an error.
/* Private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
var radioButton = sender as RadioButton;
if (radioButton == 20)
return;
int intIndex = Convert.ToInt32(radioButton.Content.ToString(Cursor.SetLimit));
}
* Remember Checked="RadioButton_Checked" in the XAML if you want to try
*/
XAML for one of the four buttons:
<RadioButton Content="RadioButton" Grid.Column="2" HorizontalAlignment="Left"
Margin="20,116,0,0" Grid.Row="2" VerticalAlignment="Top"/>
HOW SHOULD THIS ACTUALLY LOOK TO GET IT WORKING? PLEASE EDIT THE CODE (if you bother) SO I CAN SEE AND UNDERSTAND THIS.
THANKS AGAIN!
To do this in an MVVM friendly way, bind the IsChecked property like this:
IsChecked="{Binding Path=CursorLimit, Converter={StaticResource ParamToIntConverter}, ConverterParameter=10}"
Set the parameter to the correct value for the given radio button, of course. If you are not familiar with converters, you need a line in your resources like (assuming you have the local xmlns set up to point to the converter namespace):
<local:ParamToIntConverter x:Key="ParamToIntConverter"/>
Then your converter looks like:
public class ParamToIntConverter : IValueConverter
{
public object Convert (...)
{
return value.Equals(int.Parse((string)parameter));
}
public object ConvertBack(...)
{
if ((bool)value)
return int.Parse((string)parameter);
else
return Binding.DoNothing;
}
}
Your xmal code:
<RadioButton Content="RadioButton" Grid.Column="2" HorizontalAlignment="Left"
Margin="20,116,0,0" Grid.Row="2" VerticalAlignment="Top" Checked="RadioButton_Checked" />
Your *.cs code:
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
// ... do what you need for this button
}
Use different Checked="[insert_method_name]" template with equal method names in your *.cs file and do what you need in each method.
Also you can try to make it as in this http://www.dotnetperls.com/radiobutton-wpf example.

WPF UserControl command binding not udpateing UI MVVM

I have window "ClientsWindow" and it's view model class "ClientsViewModel". In ViewModel i defined property "Clients" and bound it to DataGrid's itemssource property:
private ObservableCollection<tblClient> clients;
public ObservableCollection<tblClient> Clients
{
get { return clients; }
set
{
clients = value;
OnPropertyChanged("Clients");
}
}
In my window's constructor I set this property to new value by calling the method from wcf service like this:
Clients = new ObservableCollection<tblClient>(wcf.FilterClients(PageIndex, PageSize));
And it works perfect, I get 10 records from wcf service as it should be and the list is shown in datagrid. I insert some usercontrol which I want to use for datagrid pagination. It has ChangedIndexCommand defined like this:
ChangedIndexCommandProperty =
DependencyProperty.Register("ChangedIndexCommand", typeof(ICommand), typeof(GridPaging), new UIPropertyMetadata(null));
public ICommand ChangedIndexCommand
{
get { return (ICommand)GetValue(ChangedIndexCommandProperty); }
set { SetValue(ChangedIndexCommandProperty, value); }
}
I tried to bind command form my window's viewmodel to this command, so i did it this way:
private ICommand _cmdChangedIndex;
public ICommand cmdChangedIndex
{
get
{
if (_cmdChangedIndex == null)
{
_cmdChangedIndex = new DelegateCommand(delegate()
{
worker.DoWork += worker_FilterClientsList;
worker.RunWorkerCompleted += worker_FilterClientListCompleted;
worker.RunWorkerAsync();
});
}
return _cmdChangedIndex;
}
}
private void worker_FilterClientsList(object sender, DoWorkEventArgs e)
{
try
{
ServiceClient wcf = new ServiceClient();
Clients = new ObservableCollection<tblClient>(wcf.FilterClients(PageIndex, PageSize));
TotalCount = wcf.ReturnClientsCount();
}
catch (Exception ex)
{
}
}
private void worker_FilterClientListCompleted(object sender, RunWorkerCompletedEventArgs e)
{
worker.DoWork -= worker_FilterClientsList;
}
And here is the xaml:
<pc:GridPaging PageIndex="{Binding PageIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
PageSize="{Binding PageSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TotalCount="{Binding TotalCount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Center" x:Name="clientsPagingControl"
ChangedIndexCommand="{Binding cmdChangedIndex, UpdateSourceTrigger=PropertyChanged}"
Visibility="Visible" VerticalAlignment="Top"
/>
So, while debugging everything works perfect! My command is fired when i click on the button of my userconrol, the method from wcf service is called properly and it returns new collection of items(count 2, as expected), my "Clients" property is set to new value BUT, UI still showing 10 items in my datagrid. I just cant figure out what is wrong?! Is this wrong way of binding commands to custom user controls?? Also let me note that, PageIndex, PageSize and TotalCount properties are of type int, and i bound them to my viewmodel properties, and they work perfect. But what is the problem with my command? I tried to be as clear as I could hope that you will understand what my problem is, and for any more info, please leave the comment.
OnPropertyChanged:
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
DataGrid binding:
<DataGrid IsReadOnly="True" Name="dgClients" AutoGenerateColumns="False" ItemsSource="{Binding Path=Clients, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
....
</DataGrid.Columns>
</DataGrid>
Just a thought, but it looks like you are using a BackgroundWorker class in your ICommand? In the worker_FilterClientsList method, you are setting the "Clients" observable collection property. I don't think you are able to manipulate the UI from within DoWork (it's running on a different thread). Try removing the try..catch block to see if it's hiding such an error.
You normally have to update the UI from the RunWorkerCompleted delegate (your worker_FilterClientListCompleted method).
Ok, so judging by your question, answers and the many comments, it would seem that your problem is un-reproducible. This means that you are on your own, as far as fixing your problem goes. However, this is not as bad as it sounds.
As there is no obvious problem with your displayed code, I cannot point out where your error lies. However, I can put you onto the right path to fix your own problem. It will take some time and effort on your part, but 'no pain... no gain', as they say.
One of the best ways that you find the problem in a complex project is to simplify it in a new, empty project. Normally when doing this, one of two things happens: either you find out what the problem was, or you create a concise working example that demonstrates your problem, which you can then post here (maybe as a new question, or instead of your current code). It's usually a win-win situation.
As it happens, the StackOverflow Help Center has a page to help with this. Please follow the advice in the How to create a Minimal, Complete, Tested and Readable example page to help you to simplify your problem.
One final point that I'd like to make is that normally in an application, the data access layer is separate from the UI. If you separate your different concerns like this, you will also find that it simplifies the situation further.

Loading a DataView into a DataGrid causes ShowDialog to hang?

I have this very straightforward code:
var xlData = Excel8OleDbHelper.ImportExcelFile(fileName);
var viewModel = new MyViewModel(xlData);
_window = new MyWindow(viewModel);
_window.ShowDialog();
The Excel8OleDbHelper.ImportExcelFile() method works, I can view the DataTable's content when debugging. The problem is that _window simply does not show up and the thread behaves as if it did (i.e. it's waiting for the unshown window to be closed).
If I change the code for this:
var viewModel = new MyViewModel(new DataTable());
_window = new MyWindow(viewModel);
_window.ShowDialog();
Then the window appears, but then of course with an empty grid.
The XAML for the grid:
<DataGrid x:Name="MyGrid" Margin="4"
IsReadOnly="True" SelectionUnit="Cell"
ItemsSource="{Binding Path=GridSource}" />
And the ViewModel's constructor:
public DataView GridSource { get; private set; }
public MyViewModel(DataTable dataSource)
{
GridSource = dataSource.DefaultView;
}
This is my first time using a WPF data grid so maybe I'm doing something wrong here, but I really don't see how something wrong with the grid could prevent the window from showing up at all, without giving me an exception and actually freezing my app.
Any clues? I'll gladly supply more code if anything is missing!
UPDATE
Loading an Excel workbook with 116 rows x 47 columns works; the file I need to load has 5,000+ rows x 47 columns - could it be that the WPF DataGrid requires paging for larger datasets? The WinForms DataGridView had no issues with it and was much faster, I assumed its WPF counterpart would work in a similar fashion. So the problem was that ShowDialog was waiting for the data grid to load the data. I assumed it was hung because I didn't expect the WPF DataGrid to take over a minute to do what the WinForms DataGridView did instantly.
Now that we have identified that the issue with the volume of the data:
Do you have row and column virtualization turned on ? You can set EnableRowVirtualization=true on the datagrid
Are you using auto-sized columns ? Recomputing optimal size for every new row/column can be a perf drag - Try using a fixed column size or a proportional (1*) size. You can try a similar approach with Height for Rows.
Try doing this. I am not sure this will work or not. I think loading Excel in main is causing problem or deadlocks.
var xlData = Excel8OleDbHelper.ImportExcelFile(fileName);
var viewModel = new MyViewModel(fileName);
_window = new MyWindow(viewModel);
_window.ShowDialog();
public class MyViewModel
{
public MyViewModel(string filename)
{
filename = filename;
}
private string _filename;
private DataTable _xlData;
public DataTable XlData
{
return _xlData ?? (_xlData = Excel8OleDbHelper.ImportExcelFile(fileName);
}
}

Categories