I´m trying to store some parameters for my application on a database table. The table contains multiple rows which contains a Key -> Value relationships. On my windows forms program (written in C#) I have multiple controls that should allow the user to interact with the stored configuration on the database.
For example, my database table looks like the following:
id option_name option_value
1 serial_port_baudrate 9600
2 serial_port_stopbits one
On my form I have controls that allow to change those values. After some research I've obtained the expected results using the bindingSource class and the filter property. But I have to create a bindingSource object for each textbox using the visual editor. Can you please help me to archieve this with multiple textboxes and controls without using the visual editor?
I dont know if it´s possible but I would like to code a solution where I could just name the textboxes on my form with the same name of the Key that holds the value in the database and then they would get the correct values when the application runs. I would appreciate any information or hints you could provide.
Thanks in advance.
Well, you could name all the text boxes the same as the database fields, then loop through all the textbox controls on the form. Use the name of the form as a parameter as in the below code:
DataTable table = new DataTable();
//Populate datatable
TextBox txt = new TextBox();
foreach(DataRow row in table.Rows)
{
String controlID = row["option_name"].ToString();
txt.ID = controlID;
(new TextBox()).ID = controlID;
txt.Text = table.Rows[table.Rows.IndexOf(row)][controlID].ToString();
}
This is what I use for my Options table:
void loadOptions(Control parent)
{
foreach (Control c in parent.Controls)
{
DataRow[] res = options.Select("option='" + c.Name + "'");
if (c is GroupBox)
{
loadOptions(c);
continue;
}
if (res.Length < 1) continue;
DataRow row = (DataRow)res.GetValue(0);
String value = row["value"].ToString();
if (c is TextBox)
{
c.Text = value;
}
else if (c is CheckBox)
{
((CheckBox)c).Checked = Convert.ToBoolean(value);
}
else if (c is NumericUpDown)
{
((NumericUpDown)c).Value = int.Parse(value);
}
}
}
I'm not sure if this is the best solution, but it works. I'm always looking for a better way if anybody has one.
Related
As the title says, I am looking for a way to retain the sort order of my DataGridView after refreshing the data from SQL.
If I sort any of my columns, as soon as the data is refreshed, the columns are no longer sorted and the selected row I had is no longer selected.
Is there an easy solution that would be something along the lines of:
Dim NewSort as Something
SortOrder = DataGridView1
DataGridView1.Refresh
DataGridView1.SortOrder = NewSort
I know the above code is hypothetical but I would be pleased with any solution or to be pointed in the right direction. Google and Bing have not produced helpful resources.
I assume you have a sort, you do a database refresh and your sort is gone. I've encountered this before. I created an inherited grid to handle this, but there's the general idea.
Assuming you are binding to a DataView, consider this.
' Get the Sort
string currentSort = "";
if ( grid.DataSource != null )
currentSort = ((DataView) grid.DataSource).Sort
' Reset the Data Source
grid.DataSource = yournewsource of data ' Better Be a Data View
' Recall the Sort
((DataView) grid.DataSource).Sort = currentSort
One thing I did was had an inherited grid where the data the DataSource Get property was overwritten to have this, and used the inherited grid throughout the application, rather than having to put this code everywhere. It's easy enough to change to an inherited grid if you are comfortable going into the Designer file and editing.
public class MyDataGridView : System.Windows.Forms.DataGridView
{
public object DataSource
{
get
{
return base.DataSource;
}
set
{
string currentSort = "";
if (!(base.DataSource == null))
currentSort = ((DataView)base.DataSource).Sort;
base.DataSource = value;
((DataView)base.DataSource).Sort = currentSort;
}
}
}
Ok, so what I am trying to do is click one item in a listbox that i have, that listbox gets data from the sql database depending on that the user types into the textbox.
Now when I click that item in the first listbox, I need more info related to that item to show up in the 2nd list box.
When the user enters a name in the textbox, the first 10 in sql show up, now that I have that, I need to click on one of the items and get the 'task' of that client in the next listbox. Task is MATTERS in the database.
I am pretty sure that my code is correct, I get no errors but nothing shows up in the list box.
Here is my code:
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
string item = listBox1.SelectedItem.ToString();
if (listBox1.ContainsFocus)
{
if (item == "")
{
}
else
{
var con2 = Conn.ConnString();
using (SqlConnection myConnection2 = new SqlConnection(con2))
{
string oString2 = "select CLIENTMATTERS.MATTER, CLIENTMATTERS.DESCRIPTION from CLIENTMATTERS join CLIENTCODES on CLIENTMATTERS.CLIENT = CLIENTCODES.CLIENT Where CLIENTCODES.DESCRIPTION = '#code1'";
SqlCommand oCmd = new SqlCommand(oString2, myConnection2);
oCmd.Parameters.AddWithValue("#code1", item);
myConnection2.Open();
oCmd.Connection.Open();
List<string> codelist2 = new List<string>();
using (SqlDataReader oReader2 = oCmd.ExecuteReader())
{
if (oReader2.HasRows)
{
string value = string.Empty;
while (oReader2.Read())
{
codelist2.Add(oReader2["MATTER"].ToString());
}
}
}
this.listBox2.DataSource = codelist2;
}
}
}
}
You need to use BindingList<> instead of List<>.
The List<> doesn't implement the ListChanged event, so the ListBox doesn't get notified when the datasource changes.
In your example it would look like this:
BindingList<string> codelist2 = new BindingList<string>();
For further information take a look at
BindingList on MSDN.
I'm using Ektron CMS version 9.0
I have smart form content which is allocated to taxonomies e.g. I might have five smart form content items (all of same) type allocated to a taxonomy, and another three to a different taxonomy:
I need to get all content of a smart form type from a taxonomy:
public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive) where T : class
{
// TODO
}
What I have working, based on links below, is this:
public IEnumerable<TaxonomyItemData> GetListOfSmartFormFromTaxonomy(long taxonomyId)
{
TaxonomyItemCriteria criteria = new TaxonomyItemCriteria();
criteria.AddFilter(TaxonomyItemProperty.TaxonomyId, CriteriaFilterOperator.EqualTo, taxonomyId);
TaxonomyItemManager taxonomyItemManager = new TaxonomyItemManager();
List<TaxonomyItemData> taxonomyItemList = taxonomyItemManager.GetList(criteria);
return taxonomyItemList;
}
But this just gets the item's titles and ids, not the smart form data itself.
As an Ektron newbie, I don't know how to get all the items of one Smart Form type using only one call (instead of looping through each item and fetching it by ID which is not efficient)
What have I missed? I am working on this actively today and will post my findings here.
References used so far:
http://reference.ektron.com/developer/framework/Organization/TaxonomyItemManager/GetList.asp
Ektron taxonomy and library items (in v9)
EDIT
Posted my just-got-it-working solution below as an fyi and awarded closest answer as accepted. Thanks everyone for your help. Please chime in with any improvements ;)
I'd recommend using the ContentTaxonomyCriteria with the ContentManager.
long smartFormId = 42;
long taxonomyId = 127;
bool isRecursive = true;
var cm = new ContentManager();
var taxonomyCriteria = new ContentTaxonomyCriteria();
taxonomyCriteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);
taxonomyCriteria.AddFilter(taxonomyId, isRecursive);
var content = cm.GetList(taxonomyCriteria);
UPDATE
The ContentData object has a property called XmlConfiguration. When the content is based on a smartform, this property will be non-null and have a positive (non-zero) Id: content[0].XmlConfiguration.Id for example.
I often add an Extension Method to my code that will tell me whether a given ContentData is based on a smart form:
public static class ContentDataExtensions
{
public static bool IsSmartFormContent(this ContentData content)
{
return content != null && content.XmlConfiguration != null && content.XmlConfiguration.Id > 0;
}
}
That way I can take a content (or list of content) and check it very quickly in code to see if it's based on a smartform or not:
foreach (var contentData in contentList)
{
if (contentData.IsSmartFormContent())
{
// Do smart-form stuff here...
}
}
Of course, if your content is coming from the framework api and you used a criteria object that is selecting based on a specific XmlConfigurationId, then in theory you wouldn't have to use that, but it still comes in handy quite often.
I'm not quite sure I understand your organizational structure, but you do have the ability to do your own sub clauses that select directly against the database.
In this case I wouldn't use the TaxonomyItemManager, I would use the ContentManager with a special criteria:
ContentManager cApi = new ContentManager();
var criteria = new ContentCriteria();
criteria.AddFilter(ContentProperty.Id, CriteriaFilterOperator.InSubClause, "select taxonomy_item_id where taxonomy_id = " + taxonomyId);
criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartformTypeId);
var yourContent = cApi.GetList(criteria);
That should do what you're asking for (grab the content specifically that is a member of a Taxonomy while only being of a specific SmartForm config). It's worth noting you don't need the second criteria piece (XmlConfigurationId) if your Taxonomy only contains that XmlConfiguration.
For Information, this is what I came up with. Noted Brian Oliver's comment on List but using patterns from other devs, can refactor later.
To clarify, we are creating classes from the XSDs generated from the smart forms, so have smart form types to play with. Your use may be simpler that ours.
public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive = false) where T : class
{
long smartFormId = GetSmartFormIdFromType(typeof(T));
// checks here for smartformid=0
ContentManager contentManager = new ContentManager();
ContentTaxonomyCriteria criteria = new ContentTaxonomyCriteria();
// Smart Form Type
criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);
// Taxonomy
criteria.AddFilter(taxonomyId, isRecursive);
List<ContentData> contentDataList = contentManager.GetList(criteria);
IEnumerable<T> smartFormList = ConvertToSmartFormList<T>(pressReleaseDataList);
return smartFormList;
}
private IEnumerable<T> ConvertToSmartFormList<T>(List<ContentData> contentDataList) where T : class
{
List<T> smartFormList = new List<T>();
if (contentDataList != null && contentDataList.Count > 0)
{
foreach (ContentData contentData in contentDataList)
{
if (contentData.IsSmartFormContent())
{
T smartForm = GetDeserializedContent<T>(contentData.Html);
if (smartForm != null)
{
PropertyInfo property = smartForm.GetType().GetProperty("ContentId");
if (property != null)
{
property.SetValue(smartForm, contentData.Id, null);
}
smartFormList.Add(smartForm);
}
}
}
}
return smartFormList;
}
private long GetSmartFormIdFromType(Type smartFormType)
{
SmartFormConfigurationManager manager = new SmartFormConfigurationManager();
SmartFormConfigurationCriteria criteria = new SmartFormConfigurationCriteria();
// Note: Smart Form Title must match the type's name, i.e. no spaces, for this to work
criteria.AddFilter(SmartFormConfigurationProperty.Title, CriteriaFilterOperator.EqualTo, smartFormType.Name);
List<SmartFormConfigurationData> configurationData = manager.GetList(criteria);
if (configurationData == null || configurationData.Count == 0)
{
return 0;
}
return configurationData.First().Id;
}
I am very new to Telerik Reporting as well as MVC. I am using Telerik Reporting Q1 2013 and MVC 4. I want to pass some info as parameter to report. I tried by sending parameter from code behind of report, but no use. It showing all record.
What I have done is
public partial class ImmunizationRpt : Telerik.Reporting.Report
{
public ImmunizationRpt()
{
InitializeComponent();
Telerik.Reporting.ReportParameter param = new ReportParameter();
param.Name = "PatientKey";
param.Type = ReportParameterType.Integer;
param.AllowBlank = false;
param.AllowNull = false;
param.Value = 1;
param.Visible = true;
this.Report.ReportParameters.Add(param);
//this.Report.ReportParameters.Add("PatientKey",ReportParameterType.Integer,1);
}
}
If the parameter is already defined in the report, you can access it through the collection.
this.Report.ReportParameters["PatientKey"].Value = 1;
thank you for reply! i have achived this as
my report was showing all records, because i hadn't set the report to filter the records based on the parameter value. To achieve that, first we need to add the new parameter from the code behind (as i did) and then we need to add a new filter as shown in the following code:
Telerik.Reporting.Filter filter1 = new Telerik.Reporting.Filter();
filter1.Expression = "=Fields.PatientKey";
filter1.Operator = Telerik.Reporting.FilterOperator.Equal;
filter1.Value = "=Parameters.PatientKey.Value";
report.Filters.Add(filter1);
I need merely a readonly display of Linq data; no requirement to observe changes. Here's the Linq:
string ZIPCODEFIELDNAME="zip5";
DataTable DATA = (detailedQueryResult as DataTable);
IEnumerable<object> ZIPCODE_SUMMARY;
ZIPCODE_SUMMARY = from z in DATA.AsEnumerable()
group z by z.Field<string>(ZIPCODEFIELDNAME) into g
let list = g.ToList()
select new
{
zip = g.Key,
eecount = list.Count(),
// possible additional aggregate columns here
};
I am able to bind this IEnumerable<anonymous object> to a Telerik RadGridView in code-behind simply by doing this:
myRadGridView.ItemsSource = ZIPCODE_SUMMARY.ToList();
that is, without having to declare a binding in XAML or having to define any columns. How would that be accomplished using the WPF DataGrid that ships with Visual Studio? It displays only row separators when I use the identical approach. So it knows about the items in the list, just not how to fetch the columns.
I am trying to write some quick-and-dirty utilities to import a gazillion CSV files where no two of them have the same structure or same field names, and the fewer lines of setup code the better.
P.S. I am just getting into WPF and Linq, so please set ReplyToNovice=true :-)
Did you remember to set AutoGenerateColumns=true on the datagrid? If yes, try binding to an ICollectionView instead.
UPDATE:
Thats weird, the code below works fine for me. One thing though, you may have to set the datacontext of the datagrid to {Binding}, this will bind to the whole object.
public MainWindow()
{
InitializeComponent();
dgZips.ItemsSource = GetFakeZips();
}
public dynamic GetFakeZips()
{
return Enumerable.Range(1500, 10).Select(i => new { Zip = i, Count = i / 4 });
}
Xaml:
<DataGrid x:Name="dgZips" AutoGenerateColumns="True" />