Just a quick question regarding the use of the following code snippet:
var locations = CurrentItems.Select(model => model.Location);
map.SetView(LocationRect.CreateLocationRect(locations));
as suggested in this answer:
Zoom to show all locations in bing maps
I am retrieving a list of geocoordinate asynchrounsly and binding these to a Bing Map using an ObservableCollection; copying the resultant data over to the main UI thread using:
Deployment.Current.Dispatcher.BeginInvoke( ()=> {...} )
My problem is that, I can't reference the map control within the Dispatcher (or can I??), so how can I apply the new Pushpin locations to the map using:
map.SetView(LocationRect.CreateLocationRect(locations));
Thanks,
S.
Because Map ultimately derives from DependencyObject it actually has its own Dispatcher. As such you can do;
map.Dispatcher.BeginInvoke(() => map.SetView(LocationRect.CreateLocationRect(locations)));
Also, it's worth noting you only need to call BeginInvoke() if the CheckAccess() returns false. (CheckAccess is tagged with an EditorBrowsable(EditorBrowsableState.Never) attribute so it won't show up in intellisense, you'll have to type it manually). The common pattern is;
if (map.Dispatcher.CheckAccess() == false) {
map.Dispatcher.BeginInvoke(() => map.setView(LocationRect.CreateLocationRect(locations)));
} else {
map.SetView(LocationRect.CreateLocationRect(locations));
}
I perhaps you will find this post useful. To bind the view of the map and the ViewModel, the method described use a DependecyPropety : http://sveiberg.wordpress.com/2012/06/24/5/.
Related
i have made a program, which include a lot of controls. The controls would be showed and hided according to the choice of the user. That means that controls overlapped on each other at design time. now i want to change the forecolor and backcolor of all controls at design time. but i founded so hard to accomplish this task, because all the control overlapping each other. so I decided to make a for loop method to iterate the controls in the form and then check each control in turn whether it has controls. when the control has also controls in it, I call the same method and pass the control to it to change the properties for the subcontrols too. The method like so:
void setColor(ref Control con)
{
con.BackColor= System.Drawing.Color.Black;
con.ForeColor=System.Drawing.Color.Yellow;
if (con.Controls.Count > 0) { setColor(ref con); }
}
so my Form include tabControl with multiple tabPages. I iterate the tabPages and wanted to pass it to this method, but I become error "Indexer may not be passed as an out or ref parameter"
I pass it so: setColor(ref tabControl1.Controls[i]);
can you please help me to solve this problem?
I have resolved the problem.
I have removed the "ref" from method and wrote the method simply like the following:
void SetColor(Control con)
{
con.BackColor = System.Drawing.Color.Black;
con.ForeColor = System.Drawing.Color.Yellow;
if (con.Controls.Count > 0)
{
for (int i=0; i<con.Controls.Count;i++)
SetColor(con.Controls[i]);
}
}
and call it so: setColor(this.Controls[i]);
I have to modify existing application, where leaflet layers control is used - I need to display one of the base layers when the map is initiated. Is there a way, how to call some function from the layers control from JS script - something like control.select(1) ....? If not, how can add a tile layer in the same way as it is done by the control - when I add new L.TileLayer during map init, it's not overwritten by manual layers control selection change?
You could try to emulate a user click on the Leaflet Layers Control, but there is a much more simple way to achieve what you initially describe.
Normally by simply adding a layer to the map (e.g. myTileLayer.addTo(map)), if that layer is part of the base layers or overlays of the Layers Control, the latter will automatically update its status (if you added a base layer, the radio buttons will be selected accordingly; for an overlay, the corresponding checkbox will be ticked).
Now I am not sure I understood properly your last part ("when I add new L.TileLayer during map init, it's not overwritten by manual layers control selection change").
If you mean you have an unexpected behaviour because the Tile Layer you added is not changed by the Layers Control, it may be due to the fact that you are not re-using a Tile Layer that the Layers Control knows: do not use new L.TileLayer, but re-use one of the base layers or overlays.
For example:
var baselayers = {
"Tile Layer 1": L.tileLayer(/* ... */),
"Tile Layer 2": L.tileLayer(/* ... */),
"Tile Layer 3": L.tileLayer(/* ... */)
};
var overlays = {};
L.control.layers(baselayers, overlays).addTo(map);
baseLayers["Tile Layer 1"].addTo(map);
There are several ways to handle this problem.
1) You can select second baselayer by clicking on the radio input in layer control. This can be done programatically like this (not recommended):
var layerControlElement = document.getElementsByClassName('leaflet-control-layers')[0];
layerControlElement.getElementsByTagName('input')[1].click();
2) Just change the order of baseLayers passed into L.Control.Layers during initialization.
3) Extend L.Control.Layers so that it accepts some new option {"selectedBaseLayerIndex": 1}
I found this after digging in the leaflet code:
1) find the layer you want to display in control's structure _layers
2) call map.addLayer(_layers[your_layer_index].layer)
3) find your layer in control's structure _form
4) set it's checked attribute to true
Thank you ghybs. You help me to understand leaflet.
I keep base-map preference in FireBase and get it back on connection to store via Redux.
Now my Map component re-render with tileLayer from Redux.
Before I tried to pass it on props... But with leaflet, like ghybs says, you have to add it again to the map, even if you gave it with something like :
const mapRef = useRef(); //Useful to reach Map leaflet element
layerRef.current = L.control
.layers(baseMaps, null, { position: "topleft", sortLayers: true})
.addTo(map);
And after, I hook my tileLayer :
useEffect(() => {
const { leafletElement: map } = mapRef.current; //Don't forget the current...
baseMaps[tileLayer].addTo(map);
}, [tileLayer]);
return (
<Map
onbaselayerchange={(ev) => handleBaseLayerChange(ev.name)}
layers={defaultLayer(tileLayer)}
ref={mapRef}
{...fieldProps}>
<CustomersMarkers layer={layerRef} customers={customers} />
</Map>
);
If you are using jQuery you can simulate a click on the Layers control to change the base layer:
$('.leaflet-control-layers-selector')[0].click()
If you want to switch to the second map layer use the next index [1]
I am using a pieGraph and doing some page interactions based on clicking on the pie-graph. These work just fine.
<dvt:pieGraph id="graph1" tabularData="#{dc.bean.tabularData}" dataSelection="single"
selectionListener="#{dc.bean.transfersGraphSelectionListener}"/>
However I am not able to support the following use cases
Clicking outside the graph(or clicking a selected data set again) should cause the pie-graph to lose its selection.
Having a clear button on the page which forces the graph to lose its current selection.
Programmatically select one of the data sets in the graph
I checked the UIGraph API but couldn't find much information.
Any hints would be really helpful.
please add the right code to your original post. this is what your code look like
transfersGraphSelectionListener(SelectionEvent selectionEvent){
Set<GraphSelection> selectionSet = selectionEvent.getGraphSelection();
for (GraphSelection selection : selectionSet) {
if (selection instanceof DataSelection) {
DataSelection ds = (DataSelection) selection;
Set seriesKeySet = ds.getSeriesKey().keySet();
for (Object key : seriesKeySet) {
Object selectedKey = ds.getSeriesKey().get((String) key))
}
Looks like something is missing!
I'm using Actionscript 2.0 for a mobile phone and can't get my head around Events.
I'm creating a class object with all my code and using a group of functions (all as direct 1st level children of the class). There's one function that creates a Movieclip with a square on it and sets the onPress event to another function called hit:
public function draw1Sqr(sName:String,pTL:Object,sSide:Number,rgb:Number){
// create a movie clip for the Sqr
var Sqr:MovieClip=this.canvas_mc.createEmptyMovieClip(sName,this.canvas_mc.getNextHighestDepth());
// draw square
Sqr.beginFill(rgb);
//etc ...more lines
//setup properties (these are accessible in the event)
Sqr.sSide=sSide;
Sqr.sName=sName;
//setup event
Sqr.onPress = hit; // this syntax seems to lead to 'this' within
// the handler function to be Sqr (movieclip)
//Sqr.onPress = Delegate.create(this, hit);
//I've read a lot about Delegate but it seems to make things harder for me.
}
Then in my event handler, I just cannot get the scope right...
public function hit(){
for (var x in this){
trace(x + " == " + this[x]);
}
//output results
//onPress == [type Function]
//sName == bSqr_7_4
//sSide == 20
trace(eval(this["._parent"])); //undefined
trace(eval(this["._x"])); //undefined
}
For some reason, although the scope is set to the calling object (Sqr, a Movieclip) and I can access properties I defined, I can't use the 'native' properties of a Movieclip object.
Any suggestions on how I can access the _x, _y and other properties of the Movieclip object that is pressed.
Use the array accessor or the dot accessor, but not both. For example:
trace(this._parent); // OR
trace(this["_parent"]);
As for the results of your iteration, I recall AS2 being screwy on this front. IIRC only dynamic properties are returned when looping with for ... in. This prevents Objects (which often serve as hash maps) from including their native properties when all you want are the key/value pairs you set yourself.
Also - the eval() function can be easily overused. Unless you absolutely must execute a String of AS2 that you don't have at compile-time I would recommend avoiding it. Happy coding!
I was wondering if anyone has found a solution or example to actually populating the input box of a slider and having it slide to the appropriate position onBlur() .. Currently, as we all know, it just updates this value with the position you are at. So in some regards, I am trying to reverse the functionality of this amazing slider.
One link I found: http://www.webdeveloper.com/forum/archive/index.php/t-177578.html is a bit outdated, but looks like they made an attempt. However, the links to the results do not exist. I am hoping that there may be a solution out there.
I know Filament has re-engineered the slider to handle select (drop down) values, and it works flawlessly.. So the goal would be to do the same, but with an input text box.
Will this do what you want?
$("#slider-text-box").blur(function() {
$("#slider").slider('option', 'value', parseInt($(this).val()));
});
Each option on the slider has a setter as well as a getter, so you can set the value with that, as in the example above. From the documentation:
//getter
var value = $('.selector').slider('option', 'value');
//setter
$('.selector').slider('option', 'value', 37);
UPDATE:
For dual sliders you'll need to use:
$("#amount").blur(function () {
$("#slider-range").slider("values", 0, parseInt($(this).val()));
});
$("#amount2").blur(function () {
$("#slider-range").slider("values", 1, parseInt($(this).val()));
});
You'll need to use Math.min/max to make sure that one value doesn't pass the other, as the setter doesn't seem to prevent this.
You were almost there when you were using the $("#slider-range").slider("values", 0) to get each value. A lot of jQuery has that kind of get/set convention in which the extra parameter is used to set the value.
I've done some work around the jQuery UI slider to make it accept values from a textbox, it may not be exactly what you were after but could help:
http://chowamigo.blogspot.com/2009/10/jquery-ui-slider-that-uses-text-box-for.html
$slider = $("#slider");
$("#amountMin").blur(function () {
$slider.slider("values", 0,Math.min($slider.slider("values", 1),parseInt($(this).val()) ) );
$(this).val(Math.min($slider.slider("values", 1),parseInt($(this).val())));
});
$("#amountMax").blur(function () {
$slider.slider("values",1,Math.max($slider.slider("values", 0),parseInt($(this).val()) ) );
$(this).val(Math.max($slider.slider("values", 0),parseInt($(this).val())));
});
I just used martin's code and updated the id to #slider also added the math.max as he suggested so the sliders won't overlap.