WPF Printing FlowDocument not centering - wpf

I want to print a page from some text I have with a small header.
I wanted all the text to be centered on the page but I'm not sure how to do it..
Here is my code.. t is of type track which is just an object that holds information like artist name, album name, song title, and lyrics.
PrintDialog dialog = new PrintDialog();
if (dialog.ShowDialog() != true)
{ return; }
FlowDocument doc = new FlowDocument();
Section sec = new Section();
Paragraph header = new Paragraph();
Paragraph body = new Paragraph();
Bold boldSong = new Bold();
boldSong.Inlines.Add(new Run(t.Song));
header.Inlines.Add(boldSong);
header.Inlines.Add(new LineBreak());
Bold boldArtist = new Bold();
if (!string.IsNullOrWhiteSpace(t.Artist))
{
boldArtist.Inlines.Add(new Run(t.Artist));
header.Inlines.Add(boldArtist);
header.Inlines.Add(new LineBreak());
}
Bold boldAlbum = new Bold();
if (!string.IsNullOrWhiteSpace(t.Album))
{
boldAlbum.Inlines.Add(new Run(t.Album));
header.Inlines.Add(boldAlbum);
header.Inlines.Add(new LineBreak());
}
header.TextAlignment = TextAlignment.Center;
body.Inlines.Add(t.iTunesFileTrack.Lyrics);
body.TextAlignment = TextAlignment.Center;
doc.Blocks.Add(header);
doc.Blocks.Add(body);
doc.Name = "FlowDoc";
IDocumentPaginatorSource idpSource = doc;
DocumentPaginator holder = idpSource.DocumentPaginator;
holder.PageSize = new Size(dialog.PrintableAreaWidth,
dialog.PrintableAreaHeight);
dialog.PrintDocument(holder, "Lyrics");
The page prints just fine except for the fact that the whole thing clings to the left of the document when printed... I know there is some property I'm not setting correctly or not setting at all..

increase the size of the ColumnWidth property or just make it '999999'

Related

Codename one - autocompletetextfield getitem selected

I have two problems:
1) First, I want to add a map in AutoCompleteTextField exactlly in DefaultListModel and after I want to add the the listmodel in my autocompletetextField
2) How can I get the text when I select an element in the AutoCompleteTextField?
Form hi = new Form("Auto Complete", new BoxLayout(BoxLayout.Y_AXIS));
AutoCompleteTextField ac = new AutoCompleteTextField("Short", "Shock", "Sholder", "Shrek0", "3asna", "niazra");
ac.setMinimumElementsShownInPopup(5);
//final DefaultListModel<Map<String,Object>> options = new DefaultListModel<>();
final DefaultListModel<String> options = new DefaultListModel<>();
AutoCompleteTextField an = new AutoCompleteTextField(options);
hi.add(an);
ac.addListListener(a -> {
List<Object> ls = new List<>();
System.out.println("i want to display the text selected");
});
hi.add(ac);
hi.show();
When you select an item in the suggestion box of an AutoCompleteTextField the text of this item is copied to the TextField part of the AutoCompleteTextfield, but this occur only after the ListEvent.
In order to have this behavior, prefer using a Selection Listener on the DefaultListModel:
Form hi = new Form("ACTF", new BoxLayout(BoxLayout.Y_AXIS));
DefaultListModel<String> defList = new DefaultListModel<>("Red", "Green", "Blue", "Orange");
AutoCompleteTextField tf1 = new AutoCompleteTextField(defList);
defList.addSelectionListener((oldid, newid)-> Log.p(defList.getItemAt(newid)));
hi.add(tf1);
hi.show();
I don't know why, it occur two times after showing the form, but it works perfectly fine after.
Edit: If you want to display the text on screen, you must use something like this :
Form hi = new Form("ACTF", new BoxLayout(BoxLayout.Y_AXIS));
Label text = new Label("Selected text");
DefaultListModel<String> defList = new DefaultListModel<>("Red", "Green", "Blue", "Orange");
AutoCompleteTextField tf1 = new AutoCompleteTextField(defList);
defList.addSelectionListener((oldid, newid)-> {
text.setText(defList.getItemAt(newid));
hi.revalidate();
});
hi.add(text);
hi.add(tf1);
hi.show();
EDIT 2: Example with a linked map:
Form hi = new Form("ACTF", new BoxLayout(BoxLayout.Y_AXIS));
Map testMap = new HashMap<String, String>();
testMap.put("Red", "Roses are red");
testMap.put("Green", "Grass is green");
testMap.put("Blue", "Sky is blue");
testMap.put("Orange", "Apricots are orange");
Label text = new Label("Selected text");
DefaultListModel<String> defList = new DefaultListModel<>(testMap.keySet());
AutoCompleteTextField tf1 = new AutoCompleteTextField(defList);
defList.addSelectionListener((oldid, newid)-> {
text.setText((String) testMap.get(defList.getItemAt(newid)));
hi.revalidate();
});
hi.add(text);
hi.add(tf1);
hi.show();

TreeListLookupEdit - Focus Node

I'm trying to select a node in TreeListLookupEdit.
var fn = treeListLookupEdit1.FindNodeByKeyID(NodeId);
treeListLookupEdit1.Properties.TreeList.FocusedNode = fn;
My TreeListLookupEdit is already filled with the data (from an EF datasource), I need to focus the desired row and see this value in both treeListLookUpEdit1.Text (when it is in a closed state) and when I open a popup window too.
But nothing happens, it does not selects the node.
I've also tried this (Where "treeNodes" is the actual TreeList inside the TreeListLookupEdit):
treeNodes.FocusedNode = fn;
But, when I run this piece of code, it works:
treeListLookupEdit1.ShowPopup();
treeListLookupEdit1.Properties.TreeList.FocusedNode = fn;
treeListLookupEdit1.ClosePopup();
So, how to avoid using the ShowPopup?
Update
It seems, you should set EditValue
treeListLookupEdit1.EditValue = NodeId
You need to set up TreeListLookUpEdit.Properties.DisplayMember property and TreeListLookUpEdit.Properties.ValueMember property.
Set the TreeListLookUpEdit.Properties.DisplayMember property to the column that you want to display in your TreeListLookupEdit and TreeListLookUpEdit.Properties.ValueMember to ID column and use TreeListLookUpEdit.EditValue to focus node.
After that you can do something like this:
treeListLookupEdit1.EditValue = fn.GetValue("YourIDColumn");
Here is example with DataTable as data source:
var dataTable = new DataTable();
dataTable.Columns.Add("ID", typeof(int));
dataTable.Columns.Add("Parent_ID", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Rows.Add(1, null, "1");
dataTable.Rows.Add(2, null, "2");
dataTable.Rows.Add(3, null, "3");
dataTable.Rows.Add(4, 1, "1.1");
dataTable.Rows.Add(5, 1, "1.2");
dataTable.Rows.Add(6, 3, "3.1");
dataTable.Rows.Add(7, 3, "3.2");
dataTable.Rows.Add(8, 5, "1.2.1");
var treeListLookUpEdit = new TreeListLookUpEdit();
var properties = treeListLookUpEdit.Properties;
properties.DataSource = dataTable;
properties.DisplayMember = "Name";
properties.ValueMember = "ID";
var treeList = properties.TreeList;
treeList.KeyFieldName = "ID";
treeList.ParentFieldName = "Parent_ID";
treeList.RootValue = DBNull.Value;
Controls.Add(treeListLookUpEdit);
treeListLookUpEdit.Size = treeListLookUpEdit.CalcBestSize();
If you set EditValue property of this treeListLookUpEdit object for example to 5 then you will see "1.2" text in control and node with such text will be focused:
treeListLookUpEdit.EditValue = 5;

Create BandedGridView for DevExpress XtraGrid

I would like to know how the XtraGrid and the BandedGrid play togehter and are bound to the underlaying data. The documentation has some explanatory tl;dr-text but i am missing a full working example to set it up in code. So it took me about 2 hours to figure it out. Based on this blog entry
i would like to post my answer here.
If there is a better way to put the pieces together as in my answer below i would love to know about it.
First you have to know that you can bind a plain DataTable to the XtraGrid and that the creation of the banded grid is independent.
Below you can see a new instance of XtraGrid is created. It MainView is set to be a BandedGridView
private void LoadAndFillXtraGrid() // object sender, EventArgs e
{
grid = new DevExpress.XtraGrid.GridControl();
grid.Dock = DockStyle.Fill;
// set the MainView to be the BandedGrid you are creating
grid.MainView = GetBandedGridView();
// set the Datasource to a DataTable
grid.DataSource = GetDataTable();
// add the grid to the form
this.Controls.Add(grid);
grid.BringToFront();
}
Above the line grid.MainView = GetBandedGridView(); set a BandedGridView as the MainView of the Xtragrid. Below you see how to create this BandedGridView
//Create a Banded Grid View including the grindBands and the columns
private BandedGridView GetBandedGridView()
{
BandedGridView bandedView = new BandedGridView();
// Set Customer Band
SetGridBand(bandedView, "Customer",
new string[3] { "CustomerId", "LastName", "FirstName" });
SetGridBand(bandedView, "Address", new string[3] { "PLZ", "City", "Street" });
return bandedView;
}
To set up the GridBand you have to create a GridBand and attach it to the bandedGridView by calling bandedView.Columns.AddField for each column
private void SetGridBand(BandedGridView bandedView, string gridBandCaption
, string[] columnNames)
{
var gridBand = new GridBand();
gridBand.Caption = gridBandCaption;
int nrOfColumns = columnNames.Length;
BandedGridColumn[] bandedColumns = new BandedGridColumn[nrOfColumns];
for (int i = 0; i < nrOfColumns; i++)
{
bandedColumns[i] = (BandedGridColumn)bandedView.Columns.AddField(columnNames[i]);
bandedColumns[i].OwnerBand = gridBand;
bandedColumns[i].Visible = true;
}
}
The DataSource can be a plain DataTable that contains some columns. If the name of the column in the datatable matches the names of the BandedGridColumn the will be automatically mapped. As you can see i added a column NotMapped in the datatable which is not visible in the screenshot above:
private DataTable GetDataTable()
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("CustomerId", typeof(Int32)),
new DataColumn("NotMapped", typeof(Int32)),
new DataColumn("LastName", typeof(String)),
new DataColumn("FirstName", typeof(String)),
new DataColumn("PLZ", typeof(Int32)),
new DataColumn("City", typeof(String)),
new DataColumn("Street", typeof(String))
});
dt.Rows.Add(1, 0, "John", "Barista", 80245, "Manhatten", "Broadway");
dt.Rows.Add(2, 0, "Mike", "Handyman", 87032, "Brooklyn", "Martin Luther Drive");
dt.Rows.Add(3, 0, "Jane", "Teacher", 80245, "Manhatten", "Broadway 7");
dt.Rows.Add(4, 0, "Quentin", "Producer", 80245, "Manhatten", "Broadway 15");
return dt;
}
If someone has a more elegant way to put the pieces together i would love to know about it.

Selected item not showing in a WPF combobox

I'm creating a part of my window in code. For a combobox I do this:
ObservableCollection<ParamClassOption> options = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(x => x.IDParamClass == val.CompTypeParam.IDParamClass));
ComboBox combobox = new ComboBox();
combobox.Name = "combobox" + val.CompTypeParam.ParameterName.Replace(" ", "");
combobox.ItemsSource = options;
combobox.SelectedValuePath = "IDParamClass";
combobox.DisplayMemberPath = "OptionName";
if (val.ParamClassOption != null)
{
combobox.SelectedValue = val.ParamClassOption.IDParamClassOption;
}
layoutitem.Content = combobox;
I'm able to select an item from the list and save it to the database. The problem that I have is to show the saved value again upon retrieving the values back from the database. Any idea why it's not showing? val.ParamClassOption.IDParamClassOption in the second to last line above has the correct value when the record is retrieved to be displayed.
i think you forgot to bind your selected value
var binding = new Binding {Path = new PropertyPath("IDParamClassOption"), Mode = BindingMode.TwoWay, Source = val.ParamClassOption};
combobox.SetBinding(ComboBox.SelectedValueProperty, binding);
hope this helps
Thanks for the help. I ended up using a completely different approach by adding the items to the combo-box one by one. I then set the selected item to previously added value (using the Text property). Here is what my code looks like now:
if (controlType == "Combobox")
{
ComboBox combobox = new ComboBox();
combobox.Name = "combobox" + val.CompTypeParam.ParameterName.Replace(" ", "");
ObservableCollection<ParamClassOption> options = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(x => x.IDParamClass == val.CompTypeParam.IDParamClass));
combobox.Items.Clear();
foreach (ParamClassOption option in options)
{
ComboBoxItem item = new ComboBoxItem();
item.Content = option.OptionName;
combobox.Items.Add(item);
}
combobox.Text = val.ParamClassOption.OptionName;
layoutitem.Content = combobox;
}
Later when reading the value from the combobox to save to the database I did this:
ObservableCollection<ParamClassOption> option = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(o => o.IDParamClass == value.CompTypeParam.IDParamClass).Where(o => o.OptionName == combobox.Text));
value.IDParamClassOption = option[0].IDParamClassOption;

How can I use NLog's RichTextBox Target in WPF application?

How can I use RichTextBox Target in WPF application?
I don't want to have a separate window with log, I want all log messages to be outputted in richTextBox located in WPF dialog.
I've tried to use WindowsFormsHost with RichTextBox box inside but that does not worked for me: NLog opened separate Windows Form anyway.
A workaround in the mean time is to use the 3 classes available here, then follow this procedure:
Import the 3 files into your project
If not already the case, use Project > Add Reference to add references to the WPF assemblies: WindowsBase, PresentationCore, PresentationFramework.
In WpfRichTextBoxTarget.cs, replace lines 188-203 with:
//this.TargetRichTextBox.Invoke(new DelSendTheMessageToRichTextBox(this.SendTheMessageToRichTextBox), new object[] { logMessage, matchingRule });
if (System.Windows.Application.Current.Dispatcher.CheckAccess() == false) {
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => {
SendTheMessageToRichTextBox(logMessage, matchingRule);
}));
}
else {
SendTheMessageToRichTextBox(logMessage, matchingRule);
}
}
private static Color GetColorFromString(string color, Brush defaultColor) {
if (defaultColor == null) return Color.FromRgb(255, 255, 255); // This will set default background colour to white.
if (color == "Empty") {
return (Color)colorConverter.ConvertFrom(defaultColor);
}
return (Color)colorConverter.ConvertFromString(color);
}
In your code, configure the new target like this below example:
I hope it helps, but it definitely does not seem to be a comprehensive implementation...
public void loading() {
var target = new WpfRichTextBoxTarget();
target.Name = "console";
target.Layout = "${longdate:useUTC=true}|${level:uppercase=true}|${logger}::${message}";
target.ControlName = "rtbConsole"; // Name of the richtextbox control already on your window
target.FormName = "MonitorWindow"; // Name of your window where there is the richtextbox, but it seems it will not really be taken into account, the application mainwindow will be used instead.
target.AutoScroll = true;
target.MaxLines = 100000;
target.UseDefaultRowColoringRules = true;
AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
asyncWrapper.Name = "console";
asyncWrapper.WrappedTarget = target;
SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);
}
If you define a RichTextBoxTarget in the config file, a new form is automatically created. This is because NLog initializes before your (named) form and control has been created. Even if you haven't got any rules pointing to the target. Perhaps there is a better solution, but I solved it by creating the target programatically:
using NLog;
//[...]
RichTextBoxTarget target = new RichTextBoxTarget();
target.Name = "RichTextBox";
target.Layout = "${longdate} ${level:uppercase=true} ${logger} ${message}";
target.ControlName = "textbox1";
target.FormName = "Form1";
target.AutoScroll = true;
target.MaxLines = 10000;
target.UseDefaultRowColoringRules = false;
target.RowColoringRules.Add(
new RichTextBoxRowColoringRule(
"level == LogLevel.Trace", // condition
"DarkGray", // font color
"Control", // background color
FontStyle.Regular
)
);
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Debug", "Gray", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Info", "ControlText", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Warn", "DarkRed", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Error", "White", "DarkRed", FontStyle.Bold));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Fatal", "Yellow", "DarkRed", FontStyle.Bold));
AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
asyncWrapper.Name = "AsyncRichTextBox";
asyncWrapper.WrappedTarget = target;
SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);

Resources