I'm using this code:
/// <summary>
/// Converts from XAML markup to a WPF FlowDocument.
/// </summary>
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
/* See http://stackoverflow.com/questions/897505/getting-a-flowdocument-from-a-xaml-template-file */
var flowDocument = new FlowDocument();
if (value != null)
{
var xamlText = (string) value;
flowDocument = (FlowDocument)XamlReader.Parse(xamlText);
}
// Set return value
return flowDocument;
}
My problem is that while basically conversion of raw strings to flow documents works fine, trailing spaces will be removed. I don't want the trailing spaces to be removed. How can I do that?
I tried adding xml tags I found on the Internet to the string (see xml:space="preserve" effect on space between XML attributes?) but it didn't help.
Edit: When I write
flowDocument = (FlowDocument)XamlReader.Parse("<TextBlock xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xml:space='preserve'> <Run>" + xamlText + "</Run> </TextBlock>");
I get an exception.
Edit: Thanks to andy for the hint - I've now figured out how to implement it, and it works.
var xamlText = (string) value;
var idx = xamlText.IndexOf("<Run");
if (idx != -1)
xamlText = xamlText.Substring(0, idx) + "<TextBlock xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xml:space='preserve'>" + xamlText.Substring(idx);
idx = xamlText.IndexOf("</Run");
if (idx != -1)
xamlText = xamlText.Substring(0, idx + 6) + "</TextBlock>" + xamlText.Substring(idx + 6);
flowDocument = (FlowDocument)XamlReader.Parse(xamlText);
Related
I'm trying to extract the value "file version" using c#, but it keeps on coming out empty. All other values seems to be read ok. Anyone got any tips?
public static string GetExtendedFileProperty(string filePath, string propertyName)
{
string value = string.Empty;
string baseFolder = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
//Method to load and execute the Shell object for Windows server 8 environment otherwise you get "Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.Shell'"
Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
Object shell = Activator.CreateInstance(shellAppType);
Shell32.Folder shellFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { baseFolder });
//Parsename will find the specific file I'm looking for in the Shell32.Folder object
Shell32.FolderItem folderitem = shellFolder.ParseName(fileName);
if (folderitem != null)
{
for (int i = 0; i < short.MaxValue; i++)
{
//Get the property name for property index i
string property = shellFolder.GetDetailsOf(null, i);
//Will be empty when all possible properties has been looped through, break out of loop
if (String.IsNullOrEmpty(property)) break;
//Skip to next property if this is not the specified property
if (property != propertyName) continue;
//Read value of property
value = shellFolder.GetDetailsOf(folderitem, i);
Console.WriteLine(property + " -> " + value);
}
}
//returns string.Empty if no value was found for the specified property
return value;
}
Did you try FileVersionInfo.FileVersion
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(filePath);
// Print the file name and version number.
Console.WriteLine("File: " + myFileVersionInfo.FileDescription + '\n' +
"Version number: " + myFileVersionInfo.FileVersion);
I have a bunch of scripts with specific lines I need to change into others.
For example my main looks like this:
string Path = #"C:\foo\bar\bin\";
string Conf = "foo.bar.conf.bat";
string OldValue = "rem set \"PARAM =% PARAM % -Foo:BAR = foo,bar = 123,fff = bbb,aaa\"";
string NewValue = "set \"PARAM =% PARAM % -Foo:BAR = foo,bar = 123,fff = bbb,aaa\"";
Console.WriteLine(FART(Path + Conf, OldValue, NewValue));
private static string FART(string PathToFile, string OldValue, string NewValue)
{
string file = File.ReadAllText(PathToFile);
OldValue = OldValue.Replace(#"\", "");
NewValue = NewValue.Replace(#"\", "");
file = file.Replace(OldValue, NewValue);
File.WriteAllText(PathToFile, file);
string output = PathToFile + " " + OldValue + " " + NewValue;
return output;
}
The string I need to uncomment is unique in this file. My problem is that the file is changed (I can see the modified date changing) but the content is the same.
Concerning similar questions this approach should work as far as I can see..
The file located at PathToFile does not have any occurances of OldValue.
Your logic for formatting OldValue and NewValue is likely wrong.
From this line:
OldValue = OldValue.Replace(#"\", "");
I can see that you'd like to remove backslashes from OldValue, however the way you've defined OldValue:
string OldValue = "rem set \"PARAM =% PARAM % -Foo:BAR = foo,bar = 123,fff = bbb,aaa\"";
It doesn't have any backslashes to begin with.
Note that when you use \" in a string in C#, it really only inserts a ". (Unless of course you prefix your string with the #).
If you delete these two lines, it should work:
OldValue = OldValue.Replace(#"\", "");
NewValue = NewValue.Replace(#"\", "");
i have an object list and i Would like to export it in a text file.
I would like that the properties name are the column header.
I 've done this
public static void Write(IList<ValidationResultAttribute> dt, string filePath)
{
int i = 0;
StreamWriter sw = null;
sw = new StreamWriter(filePath, false);
PropertyInfo[] properties = typeof(ValidationResultAttribute).GetProperties();
// write columns header
foreach (PropertyInfo property in properties)
{
sw.Write(property.Name + " ");
}
sw.WriteLine();
// write value
foreach (ValidationResultAttribute res in dt)
{
PropertyInfo[] prop = typeof(ValidationResultAttribute).GetProperties();
foreach (PropertyInfo property in prop)
{
sw.Write(property.GetValue(res, null) + " ");
}
sw.WriteLine();
}
sw.Close();
}
}
but I've this output
PresentationName SlideName ShapeName RunIndexs Attribute Rule Fail Pass
pptTest.pptx Slide1 Rectangle 3 FontSize Value 22 1 0
pptTest.pptx Slide2 TextBox 3 FontSize Between 20and 72 1 0
there is a way to format the output txt file (value under the column)?
You can use string.format to get the desired result. Works also with sw.Write(format, args)
sw.Write("[{0,-20}|{1,10}]", "UnitPrice", 3.4457M);
will write
[UnitPrice | 3,4457]
A negative value behind the format specifier mean left align a positiv value means right align.
There is one pitfall, This methods will not truncate your data, so
sw.Write("[{0,-20}|{1,10}]", "ThisStringIsLongerThanExpected", 3.4457M);
will result in
[ThisStringIsLongerThanExpected| 3,4457]
So choose the values large enough or trim your strings to fit.
In your case you could calculate the length based on which is longer the properties name or it's value.
var values = new List<KeyValuePair<string, object>();
PropertyInfo[] properties = typeof(ValidationResultAttribute).GetProperties();
foreach (PropertyInfo property in properties)
{
values.Add(property.Name, property.GetValue(res, null);
}
foreach(var value in values)
{
var length = Math.Max(value.Key.Length, value.Value.ToString().Length);
var format = "{0,-" + length.ToString() + "} ";
sw.Write(format, value.Key);
}
sw.WriteLine();
foreach(var value in values)
{
var length = Math.Max(value.Key.Length, value.Value.ToString().Length);
var format = "{0,-" + length.ToString() + "} ";
sw.Write(format, value.Value);
}
sw.WriteLine();
Do following code changes to create tab delimited file. This file is easy to parse and easy to read.
sw.Write(property.Name + " "); change this to sw.Write(property.Name + "\t");
sw.Write(property.GetValue(res, null) + " "); change this to sw.Write(property.GetValue(res, null) + "\t");
In my database, I store phone numbers like this "7279884545". One solid string with no spaces.
In my class that stores the phone number info, I have a function that will add the correct punctuation.
public static String beautifyPhoneNumber(String number, String extension)
{
String beautifulNumber = "";
if (!String.IsNullOrEmpty(number))
{
beautifulNumber = "(" + number.Substring(0, 3) + ") " +
number.Substring(3, 3) + "-" +
number.Substring(6, 4);
}
if (!String.IsNullOrEmpty(extension))
{
beautifulNumber += " x" + extension;
}
return beautifulNumber;
}
And here is how I have the variable in the class itself.
private string _PhonePrimary;
[DisplayName("Phone Primary")]
public string PhonePrimary
{
get
{
if(this._PhonePrimary != null)
{
this._PhonePrimary = beautifyPhoneNumber(this._PhonePrimary, this.Extension);
}
return this._PhonePrimary;
}
set
{
this._PhonePrimary = value;
}
}
This works fine most of the time. The numbers are outputted to the screen in a "(727) 988-4545" or "(727) 988-4545 x12" if there is an extension for that record in the database.
The problem comes when I do a HttpPost request. The model information that is inside of the post request looks like this.
_PhonePrimary = "(727) 988-4545"
PhonePrimary = "(((7) 2) -7) -"
As noted, it looks like you're calling beautifyPhoneNumber on a number you've already beautified.
Here's an implementation using regular expressions that should get you started:
public static String BeautifyPhoneNumber(string numberToBeautify)
{
//The below gives us capture groups for each
//individual piece of the number.
var regularExpression = new Regex(#"(\d{3})(\d{3})(\d{4})(x\d*)?");
//This matches a number that's already been beautified,
//so we can guard against beautifying twice.
var alreadyBeautifulExpression = new Regex(#"(\(\d{3}\)) (\d{3})-(\d{4}) ?(x\d*)?");
var beautifulNumber = string.Empty;
var separator = "-";
var space = " ";
//This prevents us from accidentally beautifying
//something more than once
//You could also guard against this in your getter using a
//IsBeautified extension, using the alreadyBeautifulExpression above
if (alreadyBeautifulExpression.IsMatch(numberToBeautify))
{
return numberToBeautify;
}
//Trying to protect against invalid input... May be insufficient,
//Or unnecessary
if (string.IsNullOrEmpty(numberToBeautify)
|| regularExpression.Matches(numberToBeautify).Count <= 0)
{
return beautifulNumber;
}
GroupCollection groups = regularExpression.Matches(
numberToBeautify)[0].Groups;
//More protection against invalid input
if (groups.Count < 3)
{
return beautifulNumber;
}
//Given "7689131234",
beautifulNumber += "(" + groups[1] + ")" + space; //gives us "(768) "
beautifulNumber += groups[2] + separator; //gives us "(768) 913-"
beautifulNumber += groups[3]; //gives us "(768) 913-1234"
//If we have an extension, we add it.
if (groups[4] != null)
{
beautifulNumber += space + groups[4];
}
return beautifulNumber;
}
Given inputs of:
7279884545
7279884545x12
(727) 988-4545
This returns:
(727) 988-4545
(727) 988-4545 x12
(727) 988-4545
I want to print the current method call (incl. return value) to the Visual Studio Output like this:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
Func<object, object> ret = (value) =>
{
#if DEBUG
var debug = new StringBuilder();
debug.Append("MyConverter.Convert([");
debug.Append(values.Sum(v => (v != null ? v.ToString() : "null") + ',', null, v => v != null ? v.ToString() : "null"));
debug.Append("], " + targetType.ToString() + ", " + parameter.ToString() + ", " + culture.DisplayName + ") =" + value.ToString() + ";");
Debug.WriteLine(debug.ToString());
#endif
return value;
};
// [..]
}
I'm using this sometimes to achieve more informations (e.g. from a Converter as shown here) while debugging. However, that's just a roundabout way.
Is there any way to do it more flexible? Something like GetCurrentArguments (from MethodInfo)?
Since you are using it for debugging there is an option using the StackTrace and StackFrame To get the current method name, but you wont get the arguments, and there is a severe performance penalty.