|
So I have some FrameworkElements that I want to scale with a ViewBox. This works fine with normal XAML code:
<Viewbox Height="100" Width="100">
<local:InfiniteLoadDiagramBase/>
</Viewbox>
But as soon as I want to join them together and scale them appropriately to the available size I have a problem:
<ItemsControl x:Name="MyItems">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Viewbox Height="100" Width="100" Stretch="UniformToFill">
<ContentControl Content="{Binding}"/>
</Viewbox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The ViewBox simply refuses to scale them according to the set size of the ViewBox. Any ideas on how to fix this?
|
|
|
|
|
Still havent found out what was wrong with this, but here is one of the FrameworkElements Im trying to bind the ItemsControl to
public class SourceDiagramBase : FrameworkElement, INotifyPropertyChanged
{
private VisualCollection _children;
public SourceDiagramBase()
{
_children = new VisualCollection(this);
_children.Add(CreateDrawingVisual());
}
protected override int VisualChildrenCount { get { return _children.Count; } }
protected override Visual GetVisualChild(int index)
{
return _children[index];
}
public double Scale
{
get { return (double)GetValue(ScaleProperty); }
set { SetValue(ScaleProperty, value); }
}
public static readonly DependencyProperty ScaleProperty =
DependencyProperty.Register("Scale", typeof(double), typeof(SourceDiagramBase), new PropertyMetadata(20d));
protected override Size MeasureOverride(Size availableSize)
{
return new Size(this.Scale * 12d, this.Scale * 12d);
}
private DrawingVisual CreateDrawingVisual()
{
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.PushTransform(new ScaleTransform(this.Scale, this.Scale));
double thick = 0.04;
drawingContext.DrawEllipse(Brushes.Transparent, new Pen(Brushes.Black, thick), new Point(6, 6), 3,3);
drawingContext.DrawLine(new Pen(Brushes.Black, thick), new Point(6, 3), new Point(6, 2));
drawingContext.DrawLine(new Pen(Brushes.Black, thick), new Point(6, 9), new Point(6, 10));
drawingContext.DrawLine(new Pen(Brushes.Black, thick), new Point(6, 2), new Point(12, 2));
drawingContext.DrawLine(new Pen(Brushes.Black, thick), new Point(6, 10), new Point(12, 10));
drawingContext.Close();
return drawingVisual;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
|
|
|
|
|
I'm querying 3 tables with Joins:
List<PurchasingEntity> results = null;
IQueryable<PurchasingEntity> query = (from c in db.Companies
join p in db.Projects on c.Id equals p.CompanyId
join j in db.Jobs on p.Id equals j.ProjectId
select new PurchasingEntity
{
CompanyId = c.Id,
CompanyName = c.CompanyName,
ProjectId = p.Id,
ProjectName = p.ProjectName,
ProjectStatusId = p.StatusId.HasValue ? p.StatusId : 0,
JobId = j.Id,
JobNumber = j.JobId,
Phase = j.Phase,
Quantity = j.Quantity.HasValue ? j.Quantity.Value : 0,
StartDate = j.StartDate.HasValue ? j.StartDate : null,
LumberVendorId = j.LumberVendorId,
HardwareVendorId = j.HardwareVendorId,
TrussVendorId = j.TrussVendorId
});
var predicate = PredicateBuilder.True<PurchasingEntity>();
predicate = predicate.And(i => i.ProjectStatusId == awardedId);
if (companyId > 0)
{
predicate = predicate.And(i => i.CompanyId == companyId);
}
if (projectId > 0)
{
predicate = predicate.And(i => i.ProjectId == projectId);
}
if (startDate != null)
{
predicate = predicate.And(i => i.StartDate >= startDate);
}
if (endDate != null)
{
predicate = predicate.And(i => i.StartDate <= endDate);
}
results = query.Where(predicate).ToList();
I doh't want to include an Companies, Projects, or Jobs if they are marked as deleted, which is DeletedDT.HasValue.
The problem is that the PredicateBuilder is working on type PurchasingEntity which is being formed via the join.
How do I filter these out???
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
You'll need to add the filters to the base query:
from c in db.Companies
join p in db.Projects on c.Id equals p.CompanyId
join j in db.Jobs on p.Id equals j.ProjectId
where c.DeletedDT == null && p.DeletedDT == null && j.DeletedDT == null
...
Also, since you're combining all of the filters using And , you don't actually need the predicate builder. Calling Where multiple times will have the same effect.
query = query.Where(i => i.ProjectStatusId == awardedId);
if (companyId > 0)
{
query = query.Where(i => i.CompanyId == companyId);
}
if (projectId > 0)
{
query = query.Where(i => i.ProjectId == projectId);
}
if (startDate != null)
{
query = query.Where(i => i.StartDate >= startDate);
}
if (endDate != null)
{
query = query.Where(i => i.StartDate <= endDate);
}
results = query.ToList();
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
Here's my link:
<TextBlock Grid.Row="0"
Margin="5">
<Hyperlink x:Name="link">
<TextBlock Text="Purchasing"
FontSize="14"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ActionCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding ElementName=link}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Hyperlink>
</TextBlock>
I get
System.Windows.Data Error: 40 : BindingExpression path error: 'ActionCommand' property not found on 'object' ''MainWindowView' (Name='window')'. BindingExpression:Path=ActionCommand; DataItem='MainWindowView' (Name='window'); target element is 'InvokeCommandAction' (HashCode=36783718); target property is 'Command' (type 'ICommand')
It is trying to bind to the VIEW, not the VIEWMODEL. What's wrong here?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Your RelativeSource is set a Window. As WPF allows you to bind to other controls, as well as ViewModels, it makes no assumptions about what you are trying to do so it doesn't automatically try to pick up the DataContext. Try changing this to {Binding DataContext.ActionCommand, RelativeSource={RelativeSource AncestorType=Window}} instead.
This space for rent
|
|
|
|
|
That did it. Thank you.
Any thoughts on this? Probably similar but I can't seem to get it right.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I'm adding a context menu to my tabs with "Close", "Close All", and "Close All But This". Heres' the XAML:
<Style TargetType="TabItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Close All"
Command="{Binding DataContext.CloseTabCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type MenuItem}, AncestorLevel=1}}"
CommandParameter="{Binding }"/>
<MenuItem Header="Close All"
Command="{Binding DataContext.CloseAllTabsCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type MenuItem}, AncestorLevel=1}}"
CommandParameter="{Binding }"/>
<MenuItem Header="Close All But This"
Command="{Binding DataContext.CloseAllButThisTabCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type MenuItem}, AncestorLevel=1}}"
CommandParameter="{Binding }"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
The biding isn't work. The commands aren't called. Here's the output window messages:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.MenuItem', AncestorLevel='1''. BindingExpression:Path=DataContext.CloseTabCommand; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.MenuItem', AncestorLevel='1''. BindingExpression:Path=DataContext.CloseAllTabsCommand; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.MenuItem', AncestorLevel='1''. BindingExpression:Path=DataContext.CloseAllButThisTabCommand; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')
What's the right way to bind the menu item's command to the main window's VM?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
Well that didn't work. I've tried a number of things. This is what I have now.
<Style TargetType="TabItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding DataContext, ElementName=Window}">
<MenuItem Header="Close"
Command="{Binding CloseTabCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Close All Tabs"
Command="{Binding CloseAllTabsCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Close All But This"
Command="{Binding CloseAllButThisTabCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
ElementName is looking for an element named Window. If you haven't named your window "Window", that's not going to work. The RelativeSource you do in your other post should find the owning Window.
This space for rent
|
|
|
|
|
I have the window's name set to 'window'.
This is driving me nuts. I can't seem to get this right. here's what I have now:
<Style TargetType="TabItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Window}}"
x:Name="tabMenu">
<MenuItem Header="Close"
Command="{Binding CloseTabCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Close All Tabs"
Command="{Binding CloseAllTabsCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Close All But This"
Command="{Binding CloseAllButThisTabCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The Output Window shows
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContextMenu' (Name='tabMenu'); target property is 'DataContext' (type 'Object')
Again, it looks like it can't find the Window.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Sorry, I misread the part that this was a context menu. A context menu doesn't sit in the visual tree so you can't relative source back to it. What you're looking to do will be some variation of this[^].
This space for rent
|
|
|
|
|
Looks like the button's Tag property is being set to the window's DataContext, and the context menu is getting its DataContext off the button's tag.
Interesting idea. Not sure how to apply this in my style.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Following up on this.
I found a solution here.
Now my commands are firing. But the CommandParameters are all null.
Here's my XAML now:
<Style TargetType="TabItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" >
<MenuItem Header="Class Tab"
Command="{Binding Source={StaticResource Proxy}, Path=Data.CloseTabCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Class All Tabs"
Command="{Binding Source={StaticResource Proxy}, Path=Data.CloseAllTabsCommand}"
CommandParameter="{Binding}"/>
<MenuItem Header="Close All But This"
Command="{Binding Source={StaticResource Proxy}, Path=Data.CloseAllButThisTabCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tried using element name but still no luck. Any thoughts?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I'm trying to create a listbox of hyperlinks. Here's the XAML:
<ListBox ItemsSource="{Binding QuickActions}"
x:Name="quickItemList">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Grid.Row="0"
Margin="5">
<Hyperlink x:Name="link">
<TextBlock Text="{Binding Caption}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ElementName=uc, Path=DataContext.QuickActionCommand}"
CommandParameter="{Binding ElementName=quickItemList, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and the VM code:
private ICommand _QuickActionCommand;
public ICommand QuickActionCommand
{
get
{
if (_QuickActionCommand == null)
_QuickActionCommand = new RelayCommand<object>(p => QuickActionExecuted(p), p => QuickActionCanExecute());
return _QuickActionCommand;
}
}
private bool QuickActionCanExecute()
{
return true;
}
private void QuickActionExecuted(QuickActionModel model)
{
}
When I click the link the parameter 'model' is null. The SelectedItem in the list is null. I know there's a way in the XAML to code this but I just can't get it right.
Anyone know how to do this?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Caveat - this is a guess
You are passing the list in the commandparameter can you pass the selected item instead.
However I would build it differently. Bind the selected item to the VM and the textbox click event uses the selected item to get the link, no need to pass parameters from the view in the click event.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Try:
CommandParameter="{Binding}"
Your command also looks a bit odd - how does a RelayCommand<object> convert the parameter from object to QuickActionModel ?
If it still doesn't work, check the output window in Visual Studio to see if there are any binding errors.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
|
I'm creating a control in WPF that looks like this
Right now I'm designing the Bay. It's really just 3 simple nested borders.
What I want is when the mouse is over ANY part of the control (any of the 3 borders), then show the red border.
The mouseOeverBorderStyle's Setters don't like the TargetName. This has to be fairly easy. Anyone know how to do this?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Unfortunately, the IsMouseOver property doesn't work unless you have a background. However, you can set the background to "Transparent":
<Style x:Key="mouseOverBorderStyle" TargetType="{x:Type Border}" BasedOn="{StaticResource borderStyle}">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
You'll want to set the border thickness outside of the trigger; otherwise, the inner border shrinks slightly when you mouse over the control.
There's still a 2px white border around the edge which won't trigger the mouse-over behaviour. But I'm sure most people won't notice it.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Worked great. Thanks!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|