Bassicly i can load my xml file correctly into a listview but i then want the user to be able to click on the items in the listview and from their display information about that item thats not in the listview but the xml.
So i thought i could load up an xml when the user clicks on the item and somehow fetch that information but it does not display anything on the label. Any help would be appreciated thanx.
XML:
<?xml version = "1.0" encoding="utf-8"?>
<project>
<test>
<code>ss</code>
<name>test</name>
</test>
<test>
<code>ss1</code>
<name>test1</name>
</test>
</project>
code:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace form
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
XmlTextReader reader = new XmlTextReader("XMLfile1.xml");
XmlNodeType type;
while (reader.Read())
{
type = reader.NodeType;
if (type == XmlNodeType.Element)
{
if (reader.Name == "name")
{
reader.Read();
listView1.Items.Add(reader.Value);
}
}
}
reader.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
XmlTextReader reader = new XmlTextReader("XMLFile1.xml");
XmlNodeType type;
while (reader.Read())
{
type = reader.NodeType;
if (type == XmlNodeType.Element)
{
if (reader.Name == "test")
{
reader.Read();
codelabel.Text = "s";
}
}
}
}
private void groupBox2_Enter(object sender, EventArgs e)
{
}
}
}
Using these extensions,
Write:
protected string GetName(string code)
{
var item = XElement.Load("XMLfile1.xml").GetEnumerable("test", x =>
new
{
Code = x.Get("code", string.Empty),
Name = x.Get("name", string.Empty)
})
.FirstOrDefault(i => i.Code == code);
if(null != item)
return item.Name;
return "Item not found";
}
This looks up the list from the file, check's each one until it finds the right code and then returns the name value. Then place that value in your control. If I have it wrong that you are searching by name, just exchange the code in the FirstOrDefault line with the return item.Name line.
Create a class that mimics the data in your file. Like:
public class Project
{
public string Code { get; set; }
public string Name { get; set; }
}
Then, you'll read your XML file into what will end up being a List. Take a look at this tutorial:
Simple XML Parsing
private List<Project> _projects;
You would then add your data from the List to your ListView.
foreach(Project proj in _projects)
{
listView1.Items.Add(proj.Name);
}
In your ListView SelectedIndexChanged you can access the proper index of the List to display the proper value to your label.
codeLabel.Text = _projects[listView1.FocusedItem.Index].Code;
The Value property for the test node is empty (it contains only sub-nodes, no text).
I think you should change your code to accumulate the text (with declarations, you can see an example on MSDN) from beginning of test until you read its end tag.
As alternative (if the XML file is not big) you may consider to use LINQ to XML or simply an XmlDocument (it's much more easy to read and you can always have InnerXml of any node). For an example you can look this article on CodeProject.
For a short list of what you can do to parse XML you can read this article (I don't think it's very good but at least it is a...list).
Related
I am relatively new to C# and I'm working on a simple application that makes use of AvalonEdit as a small code editor embedded in the bottom of the UI.
I want to highlight all occurrences of a selected word. Right now I have this working using a DocumentColorizingTransformer as outlined by Suplanus in this question.
My code is basically identical to the implementation posted there, but it has its downsides. Mainly that the default highlighting is fighting with the new LineTransformers highlighting and there are visual artifacts that can't be avoided.
So I came across this question where Siegfried (partially) explains a way to accomplish this by using an IBackgroundRenderer class. Unfortunately there isn't a lot of code to go on. Just an outline of how to structure the draw function. There is another question where trigger_segfault posts some similar code utilizing an IBackgroundRenderer but the goal is not to highlight matching words, but search results.
So I've kind of cobbled together what I can between all of these questions and arrived here:
(Removed. See bottom of post for working code)
My question is simply, how do I pass in the matching words? Do I assign an event handler to the "SelectionChanged" event: txtSvgSource.TextArea.SelectionChanged += ValidateSelection; and then implement a setter in my HighlightSelectedWordBackgroundRenderer class to update currentResults?
I just don't understand how to pass in the words to highlight.
I'd like to move away from my current DocumentColorizingTransformer approach and properly implement the IBackgroundRenderer instead.
Anyone with experience using AvalonEdit that could point me in the right direction, your help would be extremely appreciated!
Thanks so much.
Edit 2:
I figured everything out. Here's the final working code if anyone finds this useful:
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
namespace SVGRecolorTool {
public class SearchResult : TextSegment {
/// <summary>The regex match for the search result.</summary>
public Match Match { get; }
/// <summary>Constructs the search result from the match.</summary>
public SearchResult(Match match) {
this.StartOffset = match.Index;
this.Length = match.Length;
this.Match = match;
}
}
public class HighlightSelectedWordBackgroundRenderer : IBackgroundRenderer {
private TextEditor _editor;
TextSegmentCollection<SearchResult> currentResults = new TextSegmentCollection<SearchResult>();
public HighlightSelectedWordBackgroundRenderer(TextEditor editor) {
_editor = editor;
Background = new SolidColorBrush(Color.FromArgb(90, 255, 255, 255));
Background.Freeze();
}
public KnownLayer Layer {
get { return KnownLayer.Caret; }
}
public void Draw(TextView textView, DrawingContext drawingContext) {
if (!textView.VisualLinesValid)
return;
var visualLines = textView.VisualLines;
if (visualLines.Count == 0)
return;
int viewStart = visualLines.First().FirstDocumentLine.Offset;
int viewEnd = visualLines.Last().LastDocumentLine.EndOffset;
foreach (TextSegment result in currentResults.FindOverlappingSegments(viewStart, viewEnd - viewStart)) {
BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder();
geoBuilder.AlignToWholePixels = true;
geoBuilder.CornerRadius = 0;
geoBuilder.AddSegment(textView, result);
Geometry geometry = geoBuilder.CreateGeometry();
if (geometry != null) {
drawingContext.DrawGeometry(Background, null, geometry);
}
}
}
public TextSegmentCollection<SearchResult> CurrentResults {
get { return currentResults; }
}
public Brush Background { get; set; }
}
}
_renderer = new HighlightSelectedWordBackgroundRenderer(txtSvgSource);
txtSvgSource.TextArea.TextView.BackgroundRenderers.Add(_renderer);
txtSvgSource.TextArea.SelectionChanged += HighlightSelection;
private void HighlightSelection(object sender, EventArgs e) {
_renderer.CurrentResults.Clear();
if(txtSvgSource.SelectedText.Length > 2) {
string pattern = #"\b" + txtSvgSource.SelectedText + #"\b";
Regex rg = new Regex(pattern);
MatchCollection matchedSelections = rg.Matches(txtSvgSource.Text);
if (matchedSelections.Count > 1) {
foreach (Match result in matchedSelections) {
_renderer.CurrentResults.Add(new SearchResult(result));
}
} else {
_renderer.CurrentResults.Clear();
}
} else {
_renderer.CurrentResults.Clear();
}
txtSvgSource.TextArea.TextView.InvalidateLayer(KnownLayer.Selection);
}
I'm trying to create a dynamic news html page.
The problem occurs when I try to create the html dynamically. I'm new to C#, and don't know what's wrong. Here is my c# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using NewsAPI;
using NewsAPI.Models;
using NewsAPI.Constants;
namespace NewsDemo
{
public partial class Default1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
LoadNewsPage();
}
}
protected void LoadNewsPage()
{
try
{
var newsApiClient = new NewsApiClient("key");
List<string> mylist = new List<string>();
mylist.Add("google-news");
mylist.Add("bbc-news");
mylist.Add("cnn");
mylist.Add("the-new-york-times");
var articlesResponse = newsApiClient.GetTopHeadlines(new TopHeadlinesRequest
{
Sources = mylist,
Language = Languages.EN
});
if (articlesResponse.Status == Statuses.Ok)
{
string resulHtml = "";
resulHtml += "<table>";
foreach (var article in articlesResponse.Articles)
{
resulHtml += string.Format("<tr style='valign:top'>", "");
resulHtml += string.Format("<td width=20%><img src='{0}' width='250px' height='200px'></img></td>", article.UrlToImage);
resulHtml += string.Format("<td width=80%><a href='{0}'><h3>{1}</h3></a>{1}<br>{2}<br>{3}<br><br></td>", article.Url, article.Title, article.Author, article.Description);
resulHtml += string.Format("</tr>", "");
}
resulHtml += string.Format("</table>", "");
Label1.Text = resulHtml;
}
}
catch (Exception ex)
{
throw;
}
}
}
}
Whenever I try to run it, (in VS), Chrome opens and the page never loads. I have no idea what is wrong, as I have a console app that can fetch the news and that works fine.
Any help appreciated.
Thanks!
EDIT
Your comments to my answer helped my understand more.
I think your problem doesn't depend on your code but on a known problem with Chrome+Visual Studio
In short:
Either you can debug with another browser
Or you disable JavaScript debugging
I tested your LoadNewsPage() and it does get HTML just fine.
What seems strange is that you are inserting the HTML into the text of a Label.
Instead of doing that, add this HTML in your markup:
<div id="MyNewsSection" runat="server"></div>
And then replace this
Label1.Text = resulHtml;
with
MyNewsSection.InnerHtml = resulHtml;
Also, as a general debugging help, press F12 when in Chrome: if there are any errors, they will be shown to you.
I want to get the node's keys just 'only in view' on treeview.
Here is the example;
I am using below code to get all node recursively. It just return all nodes key as expected. however i need to get the keys that only in treeview's view;
public void PrintNodesRecursive(UltraTreeNode oParentNode)
{
if (oParentNode.Nodes.Count == 0)
{
return;
}
foreach (UltraTreeNode oSubNode in oParentNode.Nodes)
{
MessageBox.Show(oSubNode.Key.ToString());
PrintNodesRecursive(oSubNode);
}
}
private void ultraButton3_Click(object sender, EventArgs e)
{
PrintNodesRecursive(ultraTree1.Nodes[0]);
}
I don't know i should follow different path or just reorganize code.
I just stacked after many hours. Need your help.
You can find the first visible node using Nodes collection and IsVisible property of the Node. Then create a recursive method which uses NextVisibleNode to find the next visible node in TreeView.
private void button1_Click(object sender, EventArgs e)
{
var visibleNodes = GetVisibleNodes(treeView1).ToList();
}
public IEnumerable<TreeNode> GetVisibleNodes(TreeView t)
{
var node = t.Nodes.Cast<TreeNode>().Where(x => x.IsVisible).FirstOrDefault();
while (node != null)
{
var temp = node;
node = node.NextVisibleNode;
yield return temp;
}
}
Also as another option, you can rely on Descendants extension method to flatten the TreeView and then using IsVisible property, get all visible nodes.
I'm writing a simple first app using Winforms, C#, VS2010, and Entity Framework. Basically, I have a rich DB I'm tapping, and I've already set up the framework, successfully enough to populate a DataGridView control with a subset of the Work Order table.
Now, I want to place a combo box on the form ("cbProjectID") whose value is ProjectID and DisplayValue is ProjectNbr. I only want to put projects in the combo box list that are related to WorkOrders, and only unique ProjectIDs within that set (a project may have dozens of work orders....)
I'm assuming I need to generate a list from EF, using LINQ. I'm pretty new at LINQ, and I'm not figuring it out...Here's my code so far...
using System;
using CPASEntityFramework;
using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BrowseWorkOrders
{
public partial class BrowseWOs : Form
{
public BrowseWOs()
{
InitializeComponent();
}
private void BrowseWOs_Load(object sender, EventArgs e)
{
var context = new CPASEntities();
var query = context.tblWorkOrders.Where(c => c.ProjectID==8);
tblWorkOrderBindingSource.DataSource = query.ToList();
// Now, I want to load up the Combo Box with all the projects in the Work Order Table
}
}
}
I've been through the net trying to find a method I understand, but I'm failing. Perhaps someone can help me out. Here's my Datasource (I assume I should NOT use tblProject, but instead use the tblProject inside tblWorkOrder in order to get my subset...)
Any help and/or guidance would be appreciated.
Here's the code now...
namespace BrowseWorkOrders
{
public partial class BrowseWOs : Form
{
public BrowseWOs()
{
InitializeComponent();
}
private void BrowseWOs_Load(object sender, EventArgs e)
{
// Following loads up all Projects into the cbProjectID Combo Box
var context = new CPASEntities();
var PrID = context.qryProjectIDNbrDescs.ToList();
cbProjectID.DataSource = PrID;
cbProjectID.ValueMember = "ID";
cbProjectID.DisplayMember = "ProjectNbr";
}
private void cbProjectID_SelectedIndexChanged(object sender, EventArgs e)
{
var context = new CPASEntities();
var query = context.tblWorkOrders.Where(c => c.ProjectID == (int)cbProjectID.SelectedValue).ToList();
tblWorkOrderBindingSource.DataSource = query;
}
}
}
You need the tblProject on the top because the other is for a single WorkOrder only. However, you need to filter the list with those who have at least on WorkOrder:
var projects = context.tblProjects.Where(p => p.tblWorkOrders.Any()).ToArray();
cbProjectID.DataSource = projects;
cbProjectID.ValueMember = "ProjectID";
cbProjectID.DisplayMember = "ProjectNbr";
I'm using VS 2010 to develop an Excel 2007 COM Add-In. Because it's a VS 2010 Office Project, it targets the .NET 4.0 Client Framework. I've added a new Ribbon (XML) item called MyRibbon, so default filenames of ThisAddIn.cs, MyRibbon.cs, and MyRibbon.xml.
Everything builds fine. It publishes with a .vsto extension. When I install the add-in (via the provided Setup.exe) it takes in Excel as being installed, and is checked in the COM Add-Ins list. It also is designated to load on start up. However, either opening Excel first or opening an Excel file does not add the tab to the ribbon.
I can tell the Add-In loads because it puts "COM add-in loaded" in the first cell of the first sheet. It appears as though CreateRibbonExtensibilityObject() is not getting called.
Does anyone have any ideas, or could tell me how to display any error messages that might be getting buried?
Details below.
I've added the override of CreateRibbonExtensibilityObject():
protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new MyRibbon();
}
MyRibbon.xml looks like this, three buttons in a group inside of a tab:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="Ribbon_Load">
<ribbon>
<tabs>
<tab id="TabAdvComTracking" idMso="TabAdvComTrackingMso" label="Adv.com Tracking">
<group id="groupPrepare" label="Prepare">
<button id="GenerateNewWorkbook" idMso="GenerateNewWorkbookMso" enabled="1" size="large" onAction="GenNewWorkbook" label="Make" />
<separator visible="1"/>
<button id="ClearData" idMso="ClearDataMso" enabled="1" size="large" onAction="ClearData" label="Clear" />
</group>
<group id="GroupDoIt" idMso="GroupDoItMso" label="Just Do It">
<button id="CaptureIds" idMso="CaptureIdsMso" enabled="1" size="large" onAction="CaptureData" label="Eat" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
MyRibbon.cs looks like this:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Office = Microsoft.Office.Core;
using Excel = Microsoft.Office.Interop.Excel;
namespace AdvComTrackingAddIn
{
[ComVisible(true)]
public class MyRibbon : Office.IRibbonExtensibility
{
private Office.IRibbonUI ribbon;
public MyRibbon()
{
}
#region IRibbonExtensibility Members
public string GetCustomUI(string ribbonID)
{
//ribbonID when loaded into Excel should be Microsoft.Excel.Workbook
return GetResourceText("AdvComTrackingAddIn.MyRibbon.xml");
}
#endregion
#region Ribbon Callbacks
//Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
}
public void GenNewWorkbook(Office.IRibbonControl control)
{
Excel.Workbook newWorkBook = Globals.ThisAddIn.Application.Workbooks.Add();
Excel.Worksheet newWorkSheet = (Excel.Worksheet)newWorkBook.Worksheets.Add();
newWorkSheet.Name = "DBTS " + GetDateRange("MMDDYYYY");
}
public string GetDateRange(string format){
string day = DateTime.Now.DayOfWeek.ToString();
int offSet = 0;
if(day == "Sunday") offSet = 1;
else if(day == "Monday") offSet = 0;
else if(day == "Tuesday") offSet = -1;
else if(day == "Wednesday") offSet = -2;
else if(day == "Thursday") offSet = -3;
else if(day == "Friday") offSet = -4;
else if(day == "Saturday") offSet = -5;
DateTime MondayStartDate = DateTime.Now.AddDays(offSet);
return MondayStartDate.ToString(format) + "_" + MondayStartDate.AddDays(4).ToString(format);
}
public void ClearData(Office.IRibbonControl control)
{
Excel.Sheets wksheets = Globals.ThisAddIn.Application.Worksheets;
Excel.Worksheet sheet;
for(int i = 0; i < wksheets.Count; i++){
sheet = wksheets[i];
if(sheet.Name.StartsWith("DBTS")){
sheet.get_Range("A6:H12").Clear();
sheet.get_Range("A16:D22").Clear();
sheet.get_Range("A26:D10000").Clear();
}
else if(sheet.Name == "Advisory.com Activity"){
sheet.get_Range("A4:B10000").Clear();
sheet.get_Range("D4:F10000").Clear();
sheet.get_Range("H4:J10000").Clear();
}
else if(sheet.Name == "Unique Hits Per URL"){
sheet.get_Range("A4:E10000").Clear();
}
}
}
public void CaptureData(Office.IRibbonControl control)
{
}
#endregion
#region Helpers
private static string GetResourceText(string resourceName)
{
Assembly asm = Assembly.GetExecutingAssembly();
string[] resourceNames = asm.GetManifestResourceNames();
for (int i = 0; i < resourceNames.Length; ++i)
{
if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
{
using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
{
if (resourceReader != null)
{
return resourceReader.ReadToEnd();
}
}
}
}
return null;
}
#endregion
}
}
Finally, ThisAddIn.cs looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using System.IO;
using System.Reflection;
namespace AdvComTrackingAddIn
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Globals.ThisAddIn.Application.get_Range("A1").Value = "COM add-in loaded";
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
GC.Collect();
}
protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new MyRibbon();
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
I encountered the same problem. I had an incorrect path to the XML file and it was returning empty:
public string GetCustomUI(string ribbonID)
{
return GetResourceText("CheckThisIsTheCorrectNameSpace.Ribbon.xml");
}
Hard coding a Namespace as a string is not a good idea, mainly because they are not refactor-able as well as the helpful comments below.
You should remove your override of CreateRibbonExtensibilityObject. By default, this is implemented by ThisAddIn's base class, and calls CreateRibbonObjects. You can either override CreateRibbonObjects (this should return an array of all of your Ribbon objects), or just let the default implementation of CreateRibbonObjects do its thing (which is to say, reflect over the entire assembly everytime that your addin starts up).
You can read more about how all of this ties together in this blog post
I have the same problem when trying to change the default TabAddIns.
What i see is that idMso is for office bar tabs and id is for new tabs.
The following works for me.
<tab id="TabAdvComTracking" tag="TabAdvComTracking" label="Adv.com Tracking" visible="true" insertAfterMso="TabAddIns">