|
I styled an expander control. I then templated a ListView so that each ListViewItem is the expander.
The problem is that the expander doesn't fill up to the width of the list. It only appears as wide as the expander's content.
Ok, here's the XAML. I know it's alot but I thought you may want to copy & paste to see what it does. Can anyone see why the list items don't sie properly?
<Window.Resources>
<!--Colors-->
<Color x:Key="Color1">Gray</Color>
<Color x:Key="Color2">SlateGray</Color>
<Color x:Key="Color3">DarkSlateGray</Color>
<Color x:Key="Color4">Orange</Color>
<Color x:Key="HeaderGradientBrush1">DarkGray</Color>
<Color x:Key="HeaderGradientBrush2">White</Color>
<!--Brushes-->
<SolidColorBrush x:Key="ToggleButtonEllipseBorderBrush"
Color="{StaticResource Color1}" />
<SolidColorBrush x:Key="ToggleButtonArrowBrush"
Color="{StaticResource Color2}" />
<SolidColorBrush x:Key="ToggleButtonUpArrowBrush"
Color="{StaticResource Color4}" />
<SolidColorBrush x:Key="ToggleButtonRectangleBrush"
Color="{StaticResource Color2}" />
<SolidColorBrush x:Key="ToggleButtonBackgroundBrush"
Color="Transparent" />
<SolidColorBrush x:Key="ContentAreaBackgroundBrush"
Color="White" />
<SolidColorBrush x:Key="ContentAreaBorderBrush"
Color="{StaticResource Color3}" />
<SolidColorBrush x:Key="CardSeperatorBorderBrush"
Color="{StaticResource Color3}" />
<SolidColorBrush x:Key="ExpanderBorderBrush"
Color="{StaticResource Color1}" />
<SolidColorBrush x:Key="ExpanderHeaderTextColor"
Color="{StaticResource Color3}" />
<LinearGradientBrush x:Key="headerGradientBrush"
EndPoint="0.504,1.5"
StartPoint="0.504,0.03">
<GradientStop Color="{StaticResource HeaderGradientBrush1}"
Offset="0" />
<GradientStop Color="{StaticResource HeaderGradientBrush2}"
Offset="0.567" />
</LinearGradientBrush>
<!--Control template for the Toggle Button-->
<ControlTemplate x:Key="ExpanderToggleButton"
TargetType="{x:Type ToggleButton}">
<Grid Width="16"
Height="16">
<Path x:Name="UpperArrow"
Stroke="{StaticResource ToggleButtonArrowBrush}"
StrokeThickness="2"
Data="M 3,4 l 5,5 5,-5" />
<Path x:Name="LowerArrow"
Stroke="{StaticResource ToggleButtonArrowBrush}"
StrokeThickness="2"
Data="M 3,9 l 5,5 5,-5" />
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"
Content="{TemplateBinding Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="true">
<Setter Property="Data"
TargetName="UpperArrow"
Value="M 3,9 l 5,-5 5,5" />
<Setter Property="Data"
TargetName="LowerArrow"
Value="M 3,6 l 5,-5 5,5" />
<Setter Property="Stroke"
TargetName="UpperArrow"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
<Setter Property="Stroke"
TargetName="LowerArrow"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Stroke"
TargetName="UpperArrow"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
<Setter Property="Stroke"
TargetName="LowerArrow"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Expander style -->
<Style x:Key="ContactCardExpanderStyle"
TargetType="Expander">
<Setter Property="Foreground"
Value="{StaticResource ExpanderHeaderTextColor}" />
<Setter Property="Template">
<Setter.Value>
<!-- Control template for Expander -->
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Name="ContentRow"
Height="0" />
</Grid.RowDefinitions>
<!--Header Area-->
<Border Name="Border"
Grid.Row="0"
Background="{StaticResource headerGradientBrush}"
BorderBrush="{StaticResource ExpanderBorderBrush}"
BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<!--Left Rectangle-->
<Rectangle x:Name="LeftPanel"
Grid.Row="0"
Fill="{StaticResource ExpanderBorderBrush}"
Width="10"
Margin="2"
HorizontalAlignment="Left" />
<!--Toggle Button-->
<ToggleButton Grid.Column="2"
IsChecked="{Binding Path=IsExpanded,Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource ExpanderToggleButton}"
Background="{StaticResource ToggleButtonBackgroundBrush}" />
<!--Caption-->
<ContentPresenter Grid.Column="1"
Margin="5"
ContentSource="Header"
RecognizesAccessKey="True" />
</Grid>
</Border>
<!--Content Area-->
<Border Name="Content"
Grid.Row="1"
Background="{StaticResource ContentAreaBackgroundBrush}"
BorderBrush="{StaticResource ExpanderBorderBrush}"
BorderThickness="1,0,1,1"
CornerRadius="0,0,3,3">
<ContentPresenter Margin="4" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<!--This sets the foreground text to orange when the mouse is over
the control and the control is NOT expanded-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver"
Value="True" />
<Condition Property="IsExpanded"
Value="False" />
</MultiTrigger.Conditions>
<Setter Property="Foreground"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
<Setter TargetName="LeftPanel"
Property="Fill"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
</MultiTrigger>
<!--This sets the arrow and rectangle colors to orange when the mouse
is over the control and the control IS expanded-->
<Trigger Property="IsExpanded"
Value="True">
<Setter TargetName="ContentRow"
Property="Height"
Value="{Binding ElementName=Content,Path=DesiredHeight}" />
<Setter TargetName="Border"
Property="BorderBrush"
Value="{StaticResource ExpanderBorderBrush}" />
<Setter TargetName="LeftPanel"
Property="Fill"
Value="{StaticResource ToggleButtonUpArrowBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--List Item Template-->
<DataTemplate x:Key="contactCardTemplate">
<Expander Style="{StaticResource ContactCardExpanderStyle}"
Header="{Binding DisplayName}"
Margin="2,2.5,2,2.5">
</Expander>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!--Menu Row-->
<RowDefinition Height="Auto" /> <!--Toolbar Row-->
<RowDefinition Height="*" /> <!--Main Content Row-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!--Contacts Column-->
<ColumnDefinition Width="*" /> <!--Contact Info Column-->
<ColumnDefinition Width="*" /> <!--Right Panel Column-->
</Grid.ColumnDefinitions>
<!--Left side contacts list grid-->
<Grid x:Name="ContactsListGrid"
Grid.Row="2"
Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <!--Options Expander Row-->
<RowDefinition Height="*" /> <!--Contacts List-->
</Grid.RowDefinitions>
<!--Contacts List-->
<ListView x:Name="ContactsList"
Grid.Row="1"
ItemsSource="{Binding Contacts}"
SelectedItem="{Binding SelectedContact, Mode=TwoWay}"
BorderBrush="{StaticResource ContentAreaBorderBrush}"
ItemTemplate="{StaticResource contactCardTemplate}"
Margin="3" />
</Grid>
</Grid>
Everything makes sense in someone's mind
|
|
|
|
|
Try
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
|
|
|
|
|
How would changing the height of the rows affect the width of the expanders in the list?
Everything makes sense in someone's mind
|
|
|
|
|
Hi, I am using WPF Toolkit Charting controls to create a bubble chart. I have been able to plot the bubble chart but now I need each bubble to be shown as a circle with sectors like in a piechart.
My first thought is to plot the piechart in a user control that would serve as a template for the bubble datapoints in the Bubble chart - if this is possible, i have no idea how to go about it.
So is there a way to customize the bubble Datapoints of the Bubble Series in this way or can someone tell me how i can achieve something like this.
Thanks in advance.
|
|
|
|
|
Did anyone knows the method to merge cells in C1Flexgrid for WPF not the usual DataGrid? I need to look my C1Flexgrid exactly like this,
Need to merge the cells and to give a back color to it. Please help me out.
|
|
|
|
|
You are posting a lot of questions here about a commercial third party control. When you purchased the control, you will also have purchased support for it - that would be the best place to start for getting expert help with the control. You might as well get your moneys worth.
|
|
|
|
|
Hello,
I am writing my app using MVVM pattern.
I have a XamDataGrid and i need to display in it my ViewModels.
I have a collection of VMs so each VM should be a row in the DataGrid.
Also each VM has a child VM that has collection of VMs. Each such VM contains 3 properties- Field, Value and operator.
I need the DataGrid to have dynamic fields according to the fields i have (in the collection of "small" VMs). each cell will contain the right value from the small VM under the right field .
The operator value should be displayed in another operator column. All operators are the same for the VMs related to same row in the DataGrid.
Currently i did it using dependency property- i bind the collection of VMs and than build a DataTable with dynamic columns and set is as DataSource of the dataGrid.
The thing is that it is fine if my DataGrid is read-only. But i need an option to change the DataGrid values . If i will do it with current code (with dependency property) i don't know what VM to change (because the DataGrid cell is not bind to any object).
How can i still solve this so it will work with binding?
|
|
|
|
|
Right,
But i don't know the number of fields i have.
|
|
|
|
|
hello, I've started using wpf and I want to display forms or WPF page in a main form WPF when I click on a button or from menu.
|
|
|
|
|
I use a window for my main form and a page displayed in a navigation frame for my controls.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
|
thank you very much, I already know the concept of mdicontainer but I thought this is not the same for implementation wpf thank you
|
|
|
|
|
Using C# only, and not WPF, is there a way to tie a TextBlock and TextBox together so that if I put them in a ListBox, they both scroll together? This is assuming you can put two controls in a ListBox, which you might not be able to do. If not, how can I do this. I have got working my scrolling List of TextBoxes, but I want to put a Label at the front of each TextBox. Either by a string or by a TextBlock.
But, I want to do this on the fly in C# and not use any WPF. If possible.
|
|
|
|
|
Not sure about the listbox control but I would assume it will take a data template which means you should use a template with a grid/stackpanel and a textblock bound to a description field and the other textblock/box bound to the value field in your list.
Don't give me any crap about not wanting to do it in xaml, if that is the case then go back to winforms where you are meant to manipulate the view.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote:
Don't give me any crap about not wanting to do it in xaml, if that is the case then go back to winforms
Well said!
|
|
|
|
|
I don't use Winforms. And, I have my reasons for not wanting to do it in XAML.
|
|
|
|
|
I know you don't use winforms but the question goes against all the design principles of WPF. I'd be interested in the reasons for not wanting to use xaml.
I have found one and that is building a grid based on a pivot but there you don't know the number of columns.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I'm using a multilevel grid and I need to change the appearance of the grid on the fly based on a user selection. I probably could use WPF in some fashion, as I use it for other controls. But, on the fly would be better for my application. I'm under the impression that anything done in WPF can be done in straight C#.
|
|
|
|
|
Sutton Mehaffey wrote: I'm under the impression that anything done in WPF can be done in straight C#.
While that is not 100% correct, there are some thing you probably can't do in code behind, it is 100% WRONG, WPF/Silverlight is ALL about the binding, until you embrace that you are going to struggle.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I got it working with Binding. Thanks. However, I have an unresolved issue concerning the binding.
I have a global array of zone descriptions[64]. Upon entering a window, the array is copied to a temp array of descriptions. The array is bound to to a List, which includes a zone number and the zone description (called zdentry - the description is named ZoneDesc). The user can edit the description, and I want to copy the change back into the temp description variable. But, I can't figure out where the change variable is. No form of zdentry or ZoneDesc is valid and creates errors. And, it won't let me 'set' anything in the ZoneDescEntry class either.
Any ideas? Thanks.
void CreateZoneDescTable()
{
List<ZoneDescEntry> zdentry = new List<ZoneDescEntry>();
for (byte i = 0; i < 5; i++)
{
zdentry.Add(new ZoneDescEntry()
{
ZoneNum = "Zone " + (i+1),
ZoneDesc = zonedescrip[i]
});
}
if (GlobalVars.system_type == 'D')
{
for (byte i = 5; i < 64; i++)
{
zdentry.Add(new ZoneDescEntry()
{
ZoneNum = "Zone " + (i+1),
ZoneDesc = zonedescrip[i]
});
}
}
ZoneDescTable.ItemsSource = zdentry;
}
public class ZoneDescEntry
{
public string ZoneNum { get; set; }
public string ZoneDesc { get; set; }
}
}
|
|
|
|
|
Not sure how you are set up but you are not implementing OnPropertyChange on your model public class ZoneDescEntry and your collections are generic rather than ObservableCollection this indicates that there is no notification about any changes to your data.
I use a BaseModel class that implements INotifyPropertyChanged and the Model implements IEditableObject this give me control of the editing process and I get notification of the data changes.
My BaseModel
public abstract class BaseModel : INotifyPropertyChanged
{
public BaseModel() { }
#region Events
/// <summary>
/// PropertyChanged event.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private bool _IsDataChanged;
public bool IsDataChanged
{
get
{ return _IsDataChanged; }
set
{
if (_IsDataChanged == value)
{
return;
}
var oldValue = _IsDataChanged;
_IsDataChanged = value;
OnPropertyChanged("IsDataChanged");
}
}
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
if (propertyName != "IsDataChanged")
{ IsDataChanged = true; }
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// get a shallow copy of object of type T.
/// objects with other object properties has not been tested.
/// </summary>
public static T ShallowCopy<T>(object objToCopy) where T : class, new()
{
if (objToCopy == null)
{ return null; }
Type objType = typeof(T);
object oValue;
PropertyInfo oPropNew;
T objNew = Activator.CreateInstance<T>(); //hence the new() contsraint
//Debug.WriteLine(objType.Name + " = new " + objType.Name + "();");
PropertyInfo[] oPInfos = objType.GetProperties();
foreach (PropertyInfo oPInfo in oPInfos)
{
//may error if no mat
oPropNew = objType.GetProperty(oPInfo.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
oValue = oPInfo.GetValue(objToCopy, null);
oPropNew.SetValue(objNew, oValue, null);
}
return objNew;
}
public static T ReverseCopy<T>(object EditableObject, object SelectedObject) where T : class, new()
{
if (EditableObject == null)
{ return null; }
Type objType = typeof(T);
object oValue;
//Debug.WriteLine(objType.Name + " = new " + objType.Name + "();");
PropertyInfo[] oPInfos = objType.GetProperties();
foreach (PropertyInfo oPInfo in oPInfos)
{
//may error if no match
PropertyInfo oPropNew = objType.GetProperty(oPInfo.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
oValue = oPInfo.GetValue(EditableObject, null);
oPropNew.SetValue(SelectedObject, oValue, null);
}
return (T)SelectedObject;
}
}
The Model class
public class ZoneDescEntryDB : BaseModel, IEditableObject
{
private string _ZoneNum;
public string ZoneNum
{
get
{ return _ZoneNum; }
set
{
if (_ZoneNum == value)
{
return;
}
var oldValue = _ZoneNum;
_ZoneNum = value;
base.OnPropertyChanged("ZoneNum");
}
}
private string _ZoneDesc;
public string ZoneDesc
{
get
{ return _ZoneDesc; }
set
{
if (_ZoneDesc == value)
{
return;
}
var oldValue = _ZoneDesc;
_ZoneDesc = value;
base.OnPropertyChanged("ZoneDesc");
}
}
#region Edit methods
private ZoneDescEntryDB Backup { get; set; }
public void BeginEdit()
{
Backup = ShallowCopy<ZoneDescEntryDB>(this);
IsDataChanged = false;
}
public void EndEdit()
{
Backup = null;
IsDataChanged = false;
}
public void CancelEdit()
{
ReverseCopy<ZoneDescEntryDB>(Backup, this); Backup = null;
IsDataChanged = false;
}
#endregion Edit methods
}
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Thanks. I'm going to try to implement your code in some fashion. I had tried the INotifyPropertyChanged, but couldn't get it to work, because I couldn't figure out where the new value was and how to store that new value in my zonedescrip[zonenum] array.
My code should be a little simpler. The Zone number never changes (a zone is a zone). The description is the only thing that can change. And, when it does, it goes back into a zonedescrip[zonenum] array. When the user clicks on a SAVE button, the zonedescrip array gets saved into a permanent place.
I need to figure out how your Edit calls work. Maybe I don't even need a temporary zonedecrip array. Just use the permanent array as the Source and copy back to the permanent array when the user clicks on SAVE. During what part of the user editing process do the BeginEdit, EndEdit, and CancelEdit methods get called?
|
|
|
|
|
You can always fetch the ListBox control using VisualTreeHelper and then set its items to Labels intead of TextBoxes .
|
|
|
|
|
I am developing a SL4 app by applying PRISM and MVVM pattern. I'd want to make users authenticate with username and password credentials before loading the shell (a common scenario), I want to show the login page, but after bootstrapper starts, because I want to use my Authentication Service, thats registered with container, and if user authenticates then to show the shell.
|
|
|
|
|