I'm having some problems displaying the contents of a flowdocument in a flowdocumentscrollviewer. I create a generic list that holds a class which contains an int, string and a flowdocument.
In a WPF listbox, I am trying to display the flowdocument in the scrollviewer alongside a button. I use the following function called from the WPF window constructor to populate the listbox
private void populateListBox()
{
foreach(Element el in _notesList)
{
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
Button b = new Button();
b.Content = el._theID;
sp.Children.Add(b);
FlowDocumentScrollViewer fdsv = new FlowDocumentScrollViewer();
fdsv.MinWidth = 400;
fdsv.Document = el._theDoc;
sp.Children.Add(fdsv);
ListBoxItem lbi = new ListBoxItem();
lbi.Content = sp;
noteList.Items.Add(lbi);
}
}
But the code does not work. There are no errors but the scrollviewers are just blank in the listbox. I also tried storing the classes in an ObservableList and binding to the Document property but that didn't work either.
Any ideas what is happening?
Nevermind. I figured it out.
Further down in the program execution I was copying the flowdocument blocks to a merged document in a foreach statement. This doesn't work even if you use Blocks.ToList(). I eventually found a way to copy the document contents to another document here.
Related
I have a listview that I would like to add a textbox inside each gridview column cell so I can type data into it and then fetch that data.
I'm creating a datatemplate and passing it to a cell template for the GridViewColumn but when I look at the listview I can't add anything to the cell. It doesn't look like the textbox was even created.
GridViewColumn conceptColumn = new GridViewColumn();
conceptColumn.Header = conceptName;
conceptColumn.CellTemplate = this.GetDataTemplate();
this.TestModeler.Columns.Add(conceptColumn);
conceptColumn.DisplayMemberBinding = new Binding(conceptName);
private DataTemplate GetDataTemplate()
{
DataTemplate dt = new DataTemplate(typeof(TextBox));
FrameworkElementFactory txtElement = new FrameworkElementFactory(typeof(TextBox));
dt.VisualTree = txtElement;
Binding bind = new Binding();
bind.Path = new PropertyPath("Text");
bind.Mode = BindingMode.TwoWay;
txtElement.SetBinding(TextBox.TextProperty, bind);
txtElement.SetValue(TextBox.TextProperty, "test");
return dt;
}
Please take a look at the ListView Class page at MSDN where you can find a XAML example and plenty of link on how to do various things with a WPF ListView.
Of particular interest to you, please take a look at the How to: Use Templates to Style a ListView That Uses GridView page there which explains what you are trying to do (but in XAML) with examples.
MSDN should always be your first place to look as it is full of information just waiting to be read.
I have DataGrid that needs to be printed in multiple pages both horizontally and vertically. Based on exhaustive searching the closest solution i have is the one found #http://www.codeproject.com/Articles/138233/Custom-Data-Grid-Document-Paginator. However, if DataGridTemplateColumn having ComboBox as its content is printed, the resultant print output is blank combobox. Below is the screenshot of the print,
http://www.filedropper.com/datagridprint
Below is the code used to create a template column while printing,
private FrameworkElement GetTableCell(Grid grid, DataGridColumn column, object item, int columnIndex, int rowIndex)
{
FrameworkElement visualElement = null;
if (column is DataGridTemplateColumn)
{
DataGridTemplateColumn templateColumn = column as DataGridTemplateColumn;
ContentControl contentControl = new ContentControl();
contentControl.Focusable = true;
contentControl.ContentTemplate = templateColumn.CellTemplate;
contentControl.Content = item;
contentControl.SetValue(Grid.ColumnProperty, columnIndex);
contentControl.SetValue(Grid.RowProperty, rowIndex);
visualElement = contentControl;
}
The above code basically creates new content control and adds the CellTemplate associated with the grid to the newly created content, which does not work. I would like to know if there is a fix for the above code, if not, is there a working solution that would print DataGrid into multiple pages (WYSIWYG).
Thanks for your help.
I use a listview to display data like a data matrix (columns and rows). My problem is : my items are typed : MatrixCellVM.
I tried everything I found on the net to apply a DataTemplate on this items but nothing worked.
Here is the latest technique I'm using
foreach (var col in dataMatrix.Columns)
{
//create the data template
DataTemplate cellLayout = new DataTemplate();
cellLayout.DataType = typeof(MatrixCellVM);
//set up the stack panel
FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(Grid));
spFactory.Name = "myComboFactory";
//set up value textblock
FrameworkElementFactory cellValue = new FrameworkElementFactory(typeof(TextBlock));
cellValue.SetBinding(TextBlock.TextProperty, new Binding("Value"));
cellValue.SetValue(TextBlock.ToolTipProperty, "Value");
spFactory.AppendChild(cellValue);
//set the visual tree of the data template
cellLayout.VisualTree = spFactory;
gridView.Columns.Add(new GridViewColumn{
Header = col.Name,
DisplayMemberBinding = new Binding(string.Format("[{0}]", count)),
CellTemplate = cellLayout
});
count++;
}
One more thing, when I override ToString() in MatrixCellVM, the value is displayed (but with this technique I add a context menu or give any color to my value).
I solved the problem but have another one.
So what I did is pretty simple. DisplayMemberBinding and CellTemplate can't be put together.
So I deleted the whole c# code creating the datatemplate.
The only thing that remains is :
gridView.Columns.Add(
new GridViewColumn
{
Header = col.Name,
CellTemplate = (DataTemplate)listView.Resources["MatrixCellVMTemplate"]
});
Thus, I added in my xaml code defining the datatemplate.
My new problem is that my rows are arrays of MatrixCellVM (as it is a matrix, I don't have properties and I don't know by advance how many columns I will have).
That was the point of the DisplayMemberBinding = new Binding(string.Format("[{0}]",count)) code in my top post.
How could I reproduce this behavior in my datatemplate (what is the binding in my textblock).
If anything is not clear, let me know.
Thanks
If I add a control to a canvas and than removes it, I can not re-add it to the same canvas (or to any other canvas for that matter) any idea how can I reset the parent?
mainCanvas.Children.Add(item);
mainCanvas.Children.Remove(item);
mainCanvas.Children.Add(item); // Will throw an exception that parent was already set.
Thanks,
Eden.
Are you sure there is not something else going on in your code?
I just tried a new wpf application with :
public MainWindow()
{
InitializeComponent();
Button b = new Button();
b.Content = "hello";
Canvas c = new Canvas();
c.Children.Add(b);
c.Children.Remove(b);
c.Children.Add(b);
Content = c;
}
and it worked fine. Have you got any collection changed delegates?
I have a StackPanel called "MainContent".
I can dynamically fill it with UIElements like this:
TextBlock textBlock = new TextBlock();
textBlock.Text = String.Format("This is text");
textBlock.Background = new SolidColorBrush(Colors.Beige);
MainContent.Children.Add(textBlock);
Button button = new Button();
button.Content = "This is a button";
MainContent.Children.Add(button);
But I want to go beyond that and fill it with a XAML/Codebehind pair (e.g. Page or Window):
Type type = this.GetType();
Assembly assembly = type.Assembly;
Window window = (Window)assembly.CreateInstance(String.Format("{0}.{1}", type.Namespace, "Test1"));
MainContent.Children.Add(window);
But the above code complains that I can't add a "Window to a Visual". I can do window.ShowDialog() of course but then it is external to my main window.
I want the Test1 window to be embedded in my application.
How can I do this?
Added: The main question is: how can I get Window (or Page) to act as a UIElement so I can embed them dynamically in StackPanels, etc. Currently looking at XamlLoader, anyone experienced with that?
The easiest way is to have your XAML/code behind inherit from UserControl - and then everything will just work
I don't know if it's possible. But instead of filling the panel with a Window, why not fill it with the root element of the window instead. You'll get all the content and value of the window without the unneeded chrome.
Update: you can grab the root element of a window via the Dependency Property Content
Window w;
object rootElement = w.Content;
Have you tried this?
MainContent.Children.Add(window.Content);